From 95f987614c2581d93d3f2d0a2d6552c8582fe7f1 Mon Sep 17 00:00:00 2001
From: Gustavo Madeira Krieger <gustavo.m.krieger@gmail.com>
Date: Tue, 5 Dec 2023 15:06:48 -0300
Subject: [PATCH] feat(cli): add read vouchers command

---
 CHANGELOG.md                                  |   2 +-
 cmd/cartesi-rollups-cli/root/read/read.go     |   3 +
 .../root/read/vouchers/vouchers.go            |  57 +++
 .../generate/input_vouchers.graphql           |  27 +
 pkg/readerclient/generate/vouchers.graphql    |  27 +
 pkg/readerclient/generated.go                 | 470 ++++++++++++++++++
 pkg/readerclient/genqlient.yaml               |   2 +
 7 files changed, 587 insertions(+), 1 deletion(-)
 create mode 100644 cmd/cartesi-rollups-cli/root/read/vouchers/vouchers.go
 create mode 100644 pkg/readerclient/generate/input_vouchers.graphql
 create mode 100644 pkg/readerclient/generate/vouchers.graphql

diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1d129609..69a2434d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Added `cartesi-rollups-node` Go binary as a single entrypoint to execute all Cartesi Node services
 - Added unified configuration for the Node with a new set of environment variables.
 - Added `cartesi-rollups-cli` binary to help develop and debug the Cartesi Rollups node
-- Added read input and read notice to `cartesi-rollups-cli`
+- Added read input, read notice and read voucher to `cartesi-rollups-cli`
 
 ### Changed
 
diff --git a/cmd/cartesi-rollups-cli/root/read/read.go b/cmd/cartesi-rollups-cli/root/read/read.go
index c0bff3165..de47caa52 100644
--- a/cmd/cartesi-rollups-cli/root/read/read.go
+++ b/cmd/cartesi-rollups-cli/root/read/read.go
@@ -9,6 +9,8 @@ import (
 	"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read/notice"
 	"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read/notices"
 	"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read/voucher"
+	"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read/vouchers"
+
 	"github.com/spf13/cobra"
 )
 
@@ -23,4 +25,5 @@ func init() {
 	Cmd.AddCommand(notice.Cmd)
 	Cmd.AddCommand(notices.Cmd)
 	Cmd.AddCommand(voucher.Cmd)
+	Cmd.AddCommand(vouchers.Cmd)
 }
diff --git a/cmd/cartesi-rollups-cli/root/read/vouchers/vouchers.go b/cmd/cartesi-rollups-cli/root/read/vouchers/vouchers.go
new file mode 100644
index 000000000..aa77418f2
--- /dev/null
+++ b/cmd/cartesi-rollups-cli/root/read/vouchers/vouchers.go
@@ -0,0 +1,57 @@
+// (c) Cartesi and individual authors (see AUTHORS)
+// SPDX-License-Identifier: Apache-2.0 (see LICENSE)
+
+package vouchers
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/Khan/genqlient/graphql"
+	"github.com/cartesi/rollups-node/pkg/readerclient"
+	"github.com/spf13/cobra"
+)
+
+var Cmd = &cobra.Command{
+	Use:     "vouchers",
+	Short:   "Reads all vouchers. If an input is specified, reads all vouchers from that input",
+	Example: examples,
+	Run:     run,
+}
+
+const examples = `# Read all vouchers:
+cartesi-rollups-cli read vouchers`
+
+var (
+	inputIndex      int
+	graphqlEndpoint string
+)
+
+func init() {
+	Cmd.Flags().IntVar(&inputIndex, "input-index", -1,
+		"index of the input")
+
+	Cmd.Flags().StringVar(&graphqlEndpoint, "graphql-endpoint", "http://0.0.0.0:4000/graphql",
+		"address used to connect to graphql")
+}
+
+func run(cmd *cobra.Command, args []string) {
+	ctx := cmd.Context()
+	client := graphql.NewClient(graphqlEndpoint, nil)
+
+	var resp []readerclient.Voucher
+	var err error
+
+	if cmd.Flags().Changed("input-index") {
+		resp, err = readerclient.GetInputVouchers(ctx, client, inputIndex)
+		cobra.CheckErr(err)
+	} else {
+		resp, err = readerclient.GetVouchers(ctx, client)
+		cobra.CheckErr(err)
+	}
+
+	val, err := json.MarshalIndent(resp, "", "    ")
+	cobra.CheckErr(err)
+
+	fmt.Print(string(val))
+}
diff --git a/pkg/readerclient/generate/input_vouchers.graphql b/pkg/readerclient/generate/input_vouchers.graphql
new file mode 100644
index 000000000..09dc700a9
--- /dev/null
+++ b/pkg/readerclient/generate/input_vouchers.graphql
@@ -0,0 +1,27 @@
+query getInputVouchers($inputIndex: Int!) {
+  input(index: $inputIndex) {
+    index
+    vouchers {
+      edges {
+        node{
+          index
+          payload
+          destination
+          proof {
+            validity {
+              inputIndexWithinEpoch
+              outputIndexWithinInput
+              outputHashesRootHash
+              vouchersEpochRootHash
+              noticesEpochRootHash
+              machineStateHash
+              outputHashInOutputHashesSiblings
+              outputHashesInEpochSiblings
+            }
+            context
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/pkg/readerclient/generate/vouchers.graphql b/pkg/readerclient/generate/vouchers.graphql
new file mode 100644
index 000000000..bbb9d6d11
--- /dev/null
+++ b/pkg/readerclient/generate/vouchers.graphql
@@ -0,0 +1,27 @@
+query getVouchers {
+  vouchers {
+    edges {
+      node {
+        index
+        payload
+        destination
+        proof {
+          validity {
+            inputIndexWithinEpoch
+            outputIndexWithinInput
+            outputHashesRootHash
+            vouchersEpochRootHash
+            noticesEpochRootHash
+            machineStateHash
+            outputHashInOutputHashesSiblings
+            outputHashesInEpochSiblings
+          }
+          context
+        }
+        input {
+          index
+        }
+      }
+    }
+  }
+}
diff --git a/pkg/readerclient/generated.go b/pkg/readerclient/generated.go
index 2cb4c250d..0d175ef06 100644
--- a/pkg/readerclient/generated.go
+++ b/pkg/readerclient/generated.go
@@ -37,6 +37,14 @@ type __getInputNoticesInput struct {
 // GetInputIndex returns __getInputNoticesInput.InputIndex, and is useful for accessing the field via an interface.
 func (v *__getInputNoticesInput) GetInputIndex() int { return v.InputIndex }
 
+// __getInputVouchersInput is used internally by genqlient
+type __getInputVouchersInput struct {
+	InputIndex int `json:"inputIndex"`
+}
+
+// GetInputIndex returns __getInputVouchersInput.InputIndex, and is useful for accessing the field via an interface.
+func (v *__getInputVouchersInput) GetInputIndex() int { return v.InputIndex }
+
 // __getNoticeInput is used internally by genqlient
 type __getNoticeInput struct {
 	NoticeIndex int `json:"noticeIndex"`
@@ -275,6 +283,181 @@ type getInputResponse struct {
 // GetInput returns getInputResponse.Input, and is useful for accessing the field via an interface.
 func (v *getInputResponse) GetInput() getInputInput { return v.Input }
 
+// getInputVouchersInput includes the requested fields of the GraphQL type Input.
+// The GraphQL type's documentation follows.
+//
+// Request submitted to the application to advance its state
+type getInputVouchersInput struct {
+	// Input index starting from genesis
+	Index int `json:"index"`
+	// Get vouchers from this particular input with support for pagination
+	Vouchers getInputVouchersInputVouchersVoucherConnection `json:"vouchers"`
+}
+
+// GetIndex returns getInputVouchersInput.Index, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInput) GetIndex() int { return v.Index }
+
+// GetVouchers returns getInputVouchersInput.Vouchers, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInput) GetVouchers() getInputVouchersInputVouchersVoucherConnection {
+	return v.Vouchers
+}
+
+// getInputVouchersInputVouchersVoucherConnection includes the requested fields of the GraphQL type VoucherConnection.
+// The GraphQL type's documentation follows.
+//
+// Pagination result
+type getInputVouchersInputVouchersVoucherConnection struct {
+	// Pagination entries returned for the current page
+	Edges []getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdge `json:"edges"`
+}
+
+// GetEdges returns getInputVouchersInputVouchersVoucherConnection.Edges, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnection) GetEdges() []getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdge {
+	return v.Edges
+}
+
+// getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdge includes the requested fields of the GraphQL type VoucherEdge.
+// The GraphQL type's documentation follows.
+//
+// Pagination entry
+type getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdge struct {
+	// Node instance
+	Node getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher `json:"node"`
+}
+
+// GetNode returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdge.Node, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdge) GetNode() getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher {
+	return v.Node
+}
+
+// getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher includes the requested fields of the GraphQL type Voucher.
+// The GraphQL type's documentation follows.
+//
+// Representation of a transaction that can be carried out on the base layer blockchain, such as a transfer of assets
+type getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher struct {
+	// Voucher index within the context of the input that produced it
+	Index int `json:"index"`
+	// Transaction payload in Ethereum hex binary format, starting with '0x'
+	Payload string `json:"payload"`
+	// Transaction destination address in Ethereum hex binary format (20 bytes), starting with '0x'
+	Destination string `json:"destination"`
+	// Proof object that allows this voucher to be validated and executed on the base layer blockchain
+	Proof getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof `json:"proof"`
+}
+
+// GetIndex returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Index, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetIndex() int {
+	return v.Index
+}
+
+// GetPayload returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Payload, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetPayload() string {
+	return v.Payload
+}
+
+// GetDestination returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Destination, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetDestination() string {
+	return v.Destination
+}
+
+// GetProof returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Proof, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetProof() getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof {
+	return v.Proof
+}
+
+// getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof includes the requested fields of the GraphQL type Proof.
+// The GraphQL type's documentation follows.
+//
+// Data that can be used as proof to validate notices and execute vouchers on the base layer blockchain
+type getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof struct {
+	// Validity proof for an output
+	Validity getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof `json:"validity"`
+	// Data that allows the validity proof to be contextualized within submitted claims, given as a payload in Ethereum hex binary format, starting with '0x'
+	Context string `json:"context"`
+}
+
+// GetValidity returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof.Validity, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof) GetValidity() getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof {
+	return v.Validity
+}
+
+// GetContext returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof.Context, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof) GetContext() string {
+	return v.Context
+}
+
+// getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof includes the requested fields of the GraphQL type OutputValidityProof.
+// The GraphQL type's documentation follows.
+//
+// Validity proof for an output
+type getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof struct {
+	// Local input index within the context of the related epoch
+	InputIndexWithinEpoch int `json:"inputIndexWithinEpoch"`
+	// Output index within the context of the input that produced it
+	OutputIndexWithinInput int `json:"outputIndexWithinInput"`
+	// Merkle root of all output hashes of the related input, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	OutputHashesRootHash string `json:"outputHashesRootHash"`
+	// Merkle root of all voucher hashes of the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	VouchersEpochRootHash string `json:"vouchersEpochRootHash"`
+	// Merkle root of all notice hashes of the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	NoticesEpochRootHash string `json:"noticesEpochRootHash"`
+	// Hash of the machine state claimed for the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	MachineStateHash string `json:"machineStateHash"`
+	// Proof that this output hash is in the output-hashes merkle tree. This array of siblings is bottom-up ordered (from the leaf to the root). Each hash is given in Ethereum hex binary format (32 bytes), starting with '0x'.
+	OutputHashInOutputHashesSiblings []string `json:"outputHashInOutputHashesSiblings"`
+	// Proof that this output-hashes root hash is in epoch's output merkle tree. This array of siblings is bottom-up ordered (from the leaf to the root). Each hash is given in Ethereum hex binary format (32 bytes), starting with '0x'.
+	OutputHashesInEpochSiblings []string `json:"outputHashesInEpochSiblings"`
+}
+
+// GetInputIndexWithinEpoch returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.InputIndexWithinEpoch, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetInputIndexWithinEpoch() int {
+	return v.InputIndexWithinEpoch
+}
+
+// GetOutputIndexWithinInput returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputIndexWithinInput, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputIndexWithinInput() int {
+	return v.OutputIndexWithinInput
+}
+
+// GetOutputHashesRootHash returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputHashesRootHash, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputHashesRootHash() string {
+	return v.OutputHashesRootHash
+}
+
+// GetVouchersEpochRootHash returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.VouchersEpochRootHash, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetVouchersEpochRootHash() string {
+	return v.VouchersEpochRootHash
+}
+
+// GetNoticesEpochRootHash returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.NoticesEpochRootHash, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetNoticesEpochRootHash() string {
+	return v.NoticesEpochRootHash
+}
+
+// GetMachineStateHash returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.MachineStateHash, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetMachineStateHash() string {
+	return v.MachineStateHash
+}
+
+// GetOutputHashInOutputHashesSiblings returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputHashInOutputHashesSiblings, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputHashInOutputHashesSiblings() []string {
+	return v.OutputHashInOutputHashesSiblings
+}
+
+// GetOutputHashesInEpochSiblings returns getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputHashesInEpochSiblings, and is useful for accessing the field via an interface.
+func (v *getInputVouchersInputVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputHashesInEpochSiblings() []string {
+	return v.OutputHashesInEpochSiblings
+}
+
+// getInputVouchersResponse is returned by getInputVouchers on success.
+type getInputVouchersResponse struct {
+	// Get input based on its identifier
+	Input getInputVouchersInput `json:"input"`
+}
+
+// GetInput returns getInputVouchersResponse.Input, and is useful for accessing the field via an interface.
+func (v *getInputVouchersResponse) GetInput() getInputVouchersInput { return v.Input }
+
 // getInputsInputsInputConnection includes the requested fields of the GraphQL type InputConnection.
 // The GraphQL type's documentation follows.
 //
@@ -790,6 +973,183 @@ func (v *getVoucherVoucherProofValidityOutputValidityProof) GetOutputHashesInEpo
 	return v.OutputHashesInEpochSiblings
 }
 
+// getVouchersResponse is returned by getVouchers on success.
+type getVouchersResponse struct {
+	// Get vouchers with support for pagination
+	Vouchers getVouchersVouchersVoucherConnection `json:"vouchers"`
+}
+
+// GetVouchers returns getVouchersResponse.Vouchers, and is useful for accessing the field via an interface.
+func (v *getVouchersResponse) GetVouchers() getVouchersVouchersVoucherConnection { return v.Vouchers }
+
+// getVouchersVouchersVoucherConnection includes the requested fields of the GraphQL type VoucherConnection.
+// The GraphQL type's documentation follows.
+//
+// Pagination result
+type getVouchersVouchersVoucherConnection struct {
+	// Pagination entries returned for the current page
+	Edges []getVouchersVouchersVoucherConnectionEdgesVoucherEdge `json:"edges"`
+}
+
+// GetEdges returns getVouchersVouchersVoucherConnection.Edges, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnection) GetEdges() []getVouchersVouchersVoucherConnectionEdgesVoucherEdge {
+	return v.Edges
+}
+
+// getVouchersVouchersVoucherConnectionEdgesVoucherEdge includes the requested fields of the GraphQL type VoucherEdge.
+// The GraphQL type's documentation follows.
+//
+// Pagination entry
+type getVouchersVouchersVoucherConnectionEdgesVoucherEdge struct {
+	// Node instance
+	Node getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher `json:"node"`
+}
+
+// GetNode returns getVouchersVouchersVoucherConnectionEdgesVoucherEdge.Node, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdge) GetNode() getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher {
+	return v.Node
+}
+
+// getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher includes the requested fields of the GraphQL type Voucher.
+// The GraphQL type's documentation follows.
+//
+// Representation of a transaction that can be carried out on the base layer blockchain, such as a transfer of assets
+type getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher struct {
+	// Voucher index within the context of the input that produced it
+	Index int `json:"index"`
+	// Transaction payload in Ethereum hex binary format, starting with '0x'
+	Payload string `json:"payload"`
+	// Transaction destination address in Ethereum hex binary format (20 bytes), starting with '0x'
+	Destination string `json:"destination"`
+	// Proof object that allows this voucher to be validated and executed on the base layer blockchain
+	Proof getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof `json:"proof"`
+	// Input whose processing produced the voucher
+	Input getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherInput `json:"input"`
+}
+
+// GetIndex returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Index, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetIndex() int {
+	return v.Index
+}
+
+// GetPayload returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Payload, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetPayload() string {
+	return v.Payload
+}
+
+// GetDestination returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Destination, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetDestination() string {
+	return v.Destination
+}
+
+// GetProof returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Proof, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetProof() getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof {
+	return v.Proof
+}
+
+// GetInput returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher.Input, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucher) GetInput() getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherInput {
+	return v.Input
+}
+
+// getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherInput includes the requested fields of the GraphQL type Input.
+// The GraphQL type's documentation follows.
+//
+// Request submitted to the application to advance its state
+type getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherInput struct {
+	// Input index starting from genesis
+	Index int `json:"index"`
+}
+
+// GetIndex returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherInput.Index, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherInput) GetIndex() int {
+	return v.Index
+}
+
+// getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof includes the requested fields of the GraphQL type Proof.
+// The GraphQL type's documentation follows.
+//
+// Data that can be used as proof to validate notices and execute vouchers on the base layer blockchain
+type getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof struct {
+	// Validity proof for an output
+	Validity getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof `json:"validity"`
+	// Data that allows the validity proof to be contextualized within submitted claims, given as a payload in Ethereum hex binary format, starting with '0x'
+	Context string `json:"context"`
+}
+
+// GetValidity returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof.Validity, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof) GetValidity() getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof {
+	return v.Validity
+}
+
+// GetContext returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof.Context, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProof) GetContext() string {
+	return v.Context
+}
+
+// getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof includes the requested fields of the GraphQL type OutputValidityProof.
+// The GraphQL type's documentation follows.
+//
+// Validity proof for an output
+type getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof struct {
+	// Local input index within the context of the related epoch
+	InputIndexWithinEpoch int `json:"inputIndexWithinEpoch"`
+	// Output index within the context of the input that produced it
+	OutputIndexWithinInput int `json:"outputIndexWithinInput"`
+	// Merkle root of all output hashes of the related input, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	OutputHashesRootHash string `json:"outputHashesRootHash"`
+	// Merkle root of all voucher hashes of the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	VouchersEpochRootHash string `json:"vouchersEpochRootHash"`
+	// Merkle root of all notice hashes of the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	NoticesEpochRootHash string `json:"noticesEpochRootHash"`
+	// Hash of the machine state claimed for the related epoch, given in Ethereum hex binary format (32 bytes), starting with '0x'
+	MachineStateHash string `json:"machineStateHash"`
+	// Proof that this output hash is in the output-hashes merkle tree. This array of siblings is bottom-up ordered (from the leaf to the root). Each hash is given in Ethereum hex binary format (32 bytes), starting with '0x'.
+	OutputHashInOutputHashesSiblings []string `json:"outputHashInOutputHashesSiblings"`
+	// Proof that this output-hashes root hash is in epoch's output merkle tree. This array of siblings is bottom-up ordered (from the leaf to the root). Each hash is given in Ethereum hex binary format (32 bytes), starting with '0x'.
+	OutputHashesInEpochSiblings []string `json:"outputHashesInEpochSiblings"`
+}
+
+// GetInputIndexWithinEpoch returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.InputIndexWithinEpoch, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetInputIndexWithinEpoch() int {
+	return v.InputIndexWithinEpoch
+}
+
+// GetOutputIndexWithinInput returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputIndexWithinInput, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputIndexWithinInput() int {
+	return v.OutputIndexWithinInput
+}
+
+// GetOutputHashesRootHash returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputHashesRootHash, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputHashesRootHash() string {
+	return v.OutputHashesRootHash
+}
+
+// GetVouchersEpochRootHash returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.VouchersEpochRootHash, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetVouchersEpochRootHash() string {
+	return v.VouchersEpochRootHash
+}
+
+// GetNoticesEpochRootHash returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.NoticesEpochRootHash, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetNoticesEpochRootHash() string {
+	return v.NoticesEpochRootHash
+}
+
+// GetMachineStateHash returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.MachineStateHash, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetMachineStateHash() string {
+	return v.MachineStateHash
+}
+
+// GetOutputHashInOutputHashesSiblings returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputHashInOutputHashesSiblings, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputHashInOutputHashesSiblings() []string {
+	return v.OutputHashInOutputHashesSiblings
+}
+
+// GetOutputHashesInEpochSiblings returns getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof.OutputHashesInEpochSiblings, and is useful for accessing the field via an interface.
+func (v *getVouchersVouchersVoucherConnectionEdgesVoucherEdgeNodeVoucherProofValidityOutputValidityProof) GetOutputHashesInEpochSiblings() []string {
+	return v.OutputHashesInEpochSiblings
+}
+
 // The query or mutation executed by getInput.
 const getInput_Operation = `
 query getInput ($index: Int!) {
@@ -886,6 +1246,63 @@ func getInputNotices(
 	return &data, err
 }
 
+// The query or mutation executed by getInputVouchers.
+const getInputVouchers_Operation = `
+query getInputVouchers ($inputIndex: Int!) {
+	input(index: $inputIndex) {
+		index
+		vouchers {
+			edges {
+				node {
+					index
+					payload
+					destination
+					proof {
+						validity {
+							inputIndexWithinEpoch
+							outputIndexWithinInput
+							outputHashesRootHash
+							vouchersEpochRootHash
+							noticesEpochRootHash
+							machineStateHash
+							outputHashInOutputHashesSiblings
+							outputHashesInEpochSiblings
+						}
+						context
+					}
+				}
+			}
+		}
+	}
+}
+`
+
+func getInputVouchers(
+	ctx context.Context,
+	client graphql.Client,
+	inputIndex int,
+) (*getInputVouchersResponse, error) {
+	req := &graphql.Request{
+		OpName: "getInputVouchers",
+		Query:  getInputVouchers_Operation,
+		Variables: &__getInputVouchersInput{
+			InputIndex: inputIndex,
+		},
+	}
+	var err error
+
+	var data getInputVouchersResponse
+	resp := &graphql.Response{Data: &data}
+
+	err = client.MakeRequest(
+		ctx,
+		req,
+		resp,
+	)
+
+	return &data, err
+}
+
 // The query or mutation executed by getInputs.
 const getInputs_Operation = `
 query getInputs {
@@ -1086,3 +1503,56 @@ func getVoucher(
 
 	return &data, err
 }
+
+// The query or mutation executed by getVouchers.
+const getVouchers_Operation = `
+query getVouchers {
+	vouchers {
+		edges {
+			node {
+				index
+				payload
+				destination
+				proof {
+					validity {
+						inputIndexWithinEpoch
+						outputIndexWithinInput
+						outputHashesRootHash
+						vouchersEpochRootHash
+						noticesEpochRootHash
+						machineStateHash
+						outputHashInOutputHashesSiblings
+						outputHashesInEpochSiblings
+					}
+					context
+				}
+				input {
+					index
+				}
+			}
+		}
+	}
+}
+`
+
+func getVouchers(
+	ctx context.Context,
+	client graphql.Client,
+) (*getVouchersResponse, error) {
+	req := &graphql.Request{
+		OpName: "getVouchers",
+		Query:  getVouchers_Operation,
+	}
+	var err error
+
+	var data getVouchersResponse
+	resp := &graphql.Response{Data: &data}
+
+	err = client.MakeRequest(
+		ctx,
+		req,
+		resp,
+	)
+
+	return &data, err
+}
diff --git a/pkg/readerclient/genqlient.yaml b/pkg/readerclient/genqlient.yaml
index fde4be734..d909636b4 100644
--- a/pkg/readerclient/genqlient.yaml
+++ b/pkg/readerclient/genqlient.yaml
@@ -11,6 +11,8 @@ operations:
 - generate/notices.graphql
 - generate/input_notices.graphql
 - generate/voucher.graphql
+- generate/vouchers.graphql
+- generate/input_vouchers.graphql
 generated: generated.go
 package: readerclient