From 1b075161097b2cdd48869e2931d6f9bc3760c487 Mon Sep 17 00:00:00 2001 From: jinoosss Date: Tue, 30 Jul 2024 01:36:57 +0900 Subject: [PATCH] feat: add pagination and sorting --- gqlgen.yml | 3 + internal/mock/storage.go | 3 +- serve/graph/generated.go | 1644 +++++++++++++---- serve/graph/model/block_list.go | 23 + serve/graph/model/cursor.go | 101 + serve/graph/model/models_gen.go | 36 + serve/graph/model/page_info.go | 9 + serve/graph/model/transaction_list.go | 23 + serve/graph/query.resolvers.go | 116 +- serve/graph/schema/query.graphql | 6 +- serve/graph/schema/schema.graphql | 5 + serve/graph/schema/types/block_list.graphql | 23 + serve/graph/schema/types/page_info.graphql | 19 + .../schema/types/transaction_list.graphql | 19 + storage/pebble.go | 57 +- storage/pebble_test.go | 8 +- storage/types.go | 10 +- 17 files changed, 1739 insertions(+), 366 deletions(-) create mode 100644 serve/graph/model/block_list.go create mode 100644 serve/graph/model/cursor.go create mode 100644 serve/graph/model/page_info.go create mode 100644 serve/graph/model/transaction_list.go create mode 100644 serve/graph/schema/types/block_list.graphql create mode 100644 serve/graph/schema/types/page_info.graphql create mode 100644 serve/graph/schema/types/transaction_list.graphql diff --git a/gqlgen.yml b/gqlgen.yml index c35bc233..3294eac5 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -81,6 +81,9 @@ models: - github.com/99designs/gqlgen/graphql.Int - github.com/99designs/gqlgen/graphql.Int64 - github.com/99designs/gqlgen/graphql.Int32 + Cursor: + model: + - github.com/gnolang/tx-indexer/serve/graph/model.Cursor Block: model: - github.com/gnolang/tx-indexer/serve/graph/model.Block diff --git a/internal/mock/storage.go b/internal/mock/storage.go index 23ae5a1f..f6451cf7 100644 --- a/internal/mock/storage.go +++ b/internal/mock/storage.go @@ -51,7 +51,7 @@ func (m *Storage) GetTxByHash(txHash string) (*types.TxResult, error) { } // BlockIterator iterates over Blocks, limiting the results to be between the provided block numbers -func (m *Storage) BlockIterator(_, _ uint64) (storage.Iterator[*types.Block], error) { +func (m *Storage) BlockIterator(_, _ uint64, _ bool) (storage.Iterator[*types.Block], error) { panic("not implemented") // TODO: Implement } @@ -62,6 +62,7 @@ func (m *Storage) TxIterator( _ uint64, _, _ uint32, + _ bool, ) (storage.Iterator[*types.TxResult], error) { panic("not implemented") // TODO: Implement } diff --git a/serve/graph/generated.go b/serve/graph/generated.go index a95c1c62..3c5dc009 100644 --- a/serve/graph/generated.go +++ b/serve/graph/generated.go @@ -75,6 +75,16 @@ type ComplexityRoot struct { Version func(childComplexity int) int } + BlockList struct { + Edges func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + BlockListEdge struct { + Block func(childComplexity int) int + Cursor func(childComplexity int) int + } + BlockTransaction struct { ContentRaw func(childComplexity int) int Fee func(childComplexity int) int @@ -130,10 +140,16 @@ type ComplexityRoot struct { Send func(childComplexity int) int } + PageInfo struct { + First func(childComplexity int) int + HasNext func(childComplexity int) int + Last func(childComplexity int) int + } + Query struct { - Blocks func(childComplexity int, filter model.BlockFilter) int + Blocks func(childComplexity int, filter model.BlockFilter, after *model.Cursor, size *int, ascending bool) int LatestBlockHeight func(childComplexity int) int - Transactions func(childComplexity int, filter model.TransactionFilter) int + Transactions func(childComplexity int, filter model.TransactionFilter, after *model.Cursor, size *int, ascending bool) int } Subscription struct { @@ -155,6 +171,16 @@ type ComplexityRoot struct { Success func(childComplexity int) int } + TransactionList struct { + Edges func(childComplexity int) int + PageInfo func(childComplexity int) int + } + + TransactionListEdge struct { + Cursor func(childComplexity int) int + Transaction func(childComplexity int) int + } + TransactionMessage struct { Route func(childComplexity int) int TypeURL func(childComplexity int) int @@ -184,8 +210,8 @@ type ComplexityRoot struct { } type QueryResolver interface { - Transactions(ctx context.Context, filter model.TransactionFilter) ([]*model.Transaction, error) - Blocks(ctx context.Context, filter model.BlockFilter) ([]*model.Block, error) + Transactions(ctx context.Context, filter model.TransactionFilter, after *model.Cursor, size *int, ascending bool) (*model.TransactionList, error) + Blocks(ctx context.Context, filter model.BlockFilter, after *model.Cursor, size *int, ascending bool) (*model.BlockList, error) LatestBlockHeight(ctx context.Context) (int, error) } type SubscriptionResolver interface { @@ -352,6 +378,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Block.Version(childComplexity), true + case "BlockList.edges": + if e.complexity.BlockList.Edges == nil { + break + } + + return e.complexity.BlockList.Edges(childComplexity), true + + case "BlockList.pageInfo": + if e.complexity.BlockList.PageInfo == nil { + break + } + + return e.complexity.BlockList.PageInfo(childComplexity), true + + case "BlockListEdge.block": + if e.complexity.BlockListEdge.Block == nil { + break + } + + return e.complexity.BlockListEdge.Block(childComplexity), true + + case "BlockListEdge.cursor": + if e.complexity.BlockListEdge.Cursor == nil { + break + } + + return e.complexity.BlockListEdge.Cursor(childComplexity), true + case "BlockTransaction.content_raw": if e.complexity.BlockTransaction.ContentRaw == nil { break @@ -548,6 +602,27 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.MsgRun.Send(childComplexity), true + case "PageInfo.first": + if e.complexity.PageInfo.First == nil { + break + } + + return e.complexity.PageInfo.First(childComplexity), true + + case "PageInfo.hasNext": + if e.complexity.PageInfo.HasNext == nil { + break + } + + return e.complexity.PageInfo.HasNext(childComplexity), true + + case "PageInfo.last": + if e.complexity.PageInfo.Last == nil { + break + } + + return e.complexity.PageInfo.Last(childComplexity), true + case "Query.blocks": if e.complexity.Query.Blocks == nil { break @@ -558,7 +633,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Blocks(childComplexity, args["filter"].(model.BlockFilter)), true + return e.complexity.Query.Blocks(childComplexity, args["filter"].(model.BlockFilter), args["after"].(*model.Cursor), args["size"].(*int), args["ascending"].(bool)), true case "Query.latestBlockHeight": if e.complexity.Query.LatestBlockHeight == nil { @@ -577,7 +652,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.Transactions(childComplexity, args["filter"].(model.TransactionFilter)), true + return e.complexity.Query.Transactions(childComplexity, args["filter"].(model.TransactionFilter), args["after"].(*model.Cursor), args["size"].(*int), args["ascending"].(bool)), true case "Subscription.blocks": if e.complexity.Subscription.Blocks == nil { @@ -680,6 +755,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Transaction.Success(childComplexity), true + case "TransactionList.edges": + if e.complexity.TransactionList.Edges == nil { + break + } + + return e.complexity.TransactionList.Edges(childComplexity), true + + case "TransactionList.pageInfo": + if e.complexity.TransactionList.PageInfo == nil { + break + } + + return e.complexity.TransactionList.PageInfo(childComplexity), true + + case "TransactionListEdge.cursor": + if e.complexity.TransactionListEdge.Cursor == nil { + break + } + + return e.complexity.TransactionListEdge.Cursor(childComplexity), true + + case "TransactionListEdge.transaction": + if e.complexity.TransactionListEdge.Transaction == nil { + break + } + + return e.complexity.TransactionListEdge.Transaction(childComplexity), true + case "TransactionMessage.route": if e.complexity.TransactionMessage.Route == nil { break @@ -884,7 +987,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er return introspection.WrapTypeFromDef(ec.Schema(), ec.Schema().Types[name]), nil } -//go:embed "schema/query.graphql" "schema/schema.graphql" "schema/subscription.graphql" "schema/filter/block_filter.graphql" "schema/filter/transaction_filter.graphql" "schema/types/block.graphql" "schema/types/transaction.graphql" +//go:embed "schema/query.graphql" "schema/schema.graphql" "schema/subscription.graphql" "schema/filter/block_filter.graphql" "schema/filter/transaction_filter.graphql" "schema/types/block.graphql" "schema/types/block_list.graphql" "schema/types/page_info.graphql" "schema/types/transaction.graphql" "schema/types/transaction_list.graphql" var sourcesFS embed.FS func sourceData(filename string) string { @@ -902,7 +1005,10 @@ var sources = []*ast.Source{ {Name: "schema/filter/block_filter.graphql", Input: sourceData("schema/filter/block_filter.graphql"), BuiltIn: false}, {Name: "schema/filter/transaction_filter.graphql", Input: sourceData("schema/filter/transaction_filter.graphql"), BuiltIn: false}, {Name: "schema/types/block.graphql", Input: sourceData("schema/types/block.graphql"), BuiltIn: false}, + {Name: "schema/types/block_list.graphql", Input: sourceData("schema/types/block_list.graphql"), BuiltIn: false}, + {Name: "schema/types/page_info.graphql", Input: sourceData("schema/types/page_info.graphql"), BuiltIn: false}, {Name: "schema/types/transaction.graphql", Input: sourceData("schema/types/transaction.graphql"), BuiltIn: false}, + {Name: "schema/types/transaction_list.graphql", Input: sourceData("schema/types/transaction_list.graphql"), BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) @@ -937,6 +1043,33 @@ func (ec *executionContext) field_Query_blocks_args(ctx context.Context, rawArgs } } args["filter"] = arg0 + var arg1 *model.Cursor + if tmp, ok := rawArgs["after"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("after")) + arg1, err = ec.unmarshalOCursor2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx, tmp) + if err != nil { + return nil, err + } + } + args["after"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["size"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("size")) + arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["size"] = arg2 + var arg3 bool + if tmp, ok := rawArgs["ascending"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ascending")) + arg3, err = ec.unmarshalNBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ascending"] = arg3 return args, nil } @@ -952,6 +1085,33 @@ func (ec *executionContext) field_Query_transactions_args(ctx context.Context, r } } args["filter"] = arg0 + var arg1 *model.Cursor + if tmp, ok := rawArgs["after"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("after")) + arg1, err = ec.unmarshalOCursor2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx, tmp) + if err != nil { + return nil, err + } + } + args["after"] = arg1 + var arg2 *int + if tmp, ok := rawArgs["size"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("size")) + arg2, err = ec.unmarshalOInt2ᚖint(ctx, tmp) + if err != nil { + return nil, err + } + } + args["size"] = arg2 + var arg3 bool + if tmp, ok := rawArgs["ascending"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("ascending")) + arg3, err = ec.unmarshalNBoolean2bool(ctx, tmp) + if err != nil { + return nil, err + } + } + args["ascending"] = arg3 return args, nil } @@ -1913,8 +2073,8 @@ func (ec *executionContext) fieldContext_Block_txs(ctx context.Context, field gr return fc, nil } -func (ec *executionContext) _BlockTransaction_hash(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_BlockTransaction_hash(ctx, field) +func (ec *executionContext) _BlockList_edges(ctx context.Context, field graphql.CollectedField, obj *model.BlockList) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockList_edges(ctx, field) if err != nil { return graphql.Null } @@ -1927,7 +2087,7 @@ func (ec *executionContext) _BlockTransaction_hash(ctx context.Context, field gr }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Hash, nil + return obj.Edges, nil }) if err != nil { ec.Error(ctx, err) @@ -1939,26 +2099,32 @@ func (ec *executionContext) _BlockTransaction_hash(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]*model.BlockListEdge) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNBlockListEdge2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockListEdgeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_BlockTransaction_hash(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockList_edges(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "BlockTransaction", + Object: "BlockList", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "block": + return ec.fieldContext_BlockListEdge_block(ctx, field) + case "cursor": + return ec.fieldContext_BlockListEdge_cursor(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type BlockListEdge", field.Name) }, } return fc, nil } -func (ec *executionContext) _BlockTransaction_fee(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_BlockTransaction_fee(ctx, field) +func (ec *executionContext) _BlockList_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.BlockList) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockList_pageInfo(ctx, field) if err != nil { return graphql.Null } @@ -1971,7 +2137,7 @@ func (ec *executionContext) _BlockTransaction_fee(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Fee, nil + return obj.PageInfo, nil }) if err != nil { ec.Error(ctx, err) @@ -1983,32 +2149,34 @@ func (ec *executionContext) _BlockTransaction_fee(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(*model.TxFee) + res := resTmp.(*model.PageInfo) fc.Result = res - return ec.marshalNTxFee2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTxFee(ctx, field.Selections, res) + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_BlockTransaction_fee(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockList_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "BlockTransaction", + Object: "BlockList", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "gas_wanted": - return ec.fieldContext_TxFee_gas_wanted(ctx, field) - case "gas_fee": - return ec.fieldContext_TxFee_gas_fee(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type TxFee", field.Name) + case "first": + return ec.fieldContext_PageInfo_first(ctx, field) + case "last": + return ec.fieldContext_PageInfo_last(ctx, field) + case "hasNext": + return ec.fieldContext_PageInfo_hasNext(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name) }, } return fc, nil } -func (ec *executionContext) _BlockTransaction_memo(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_BlockTransaction_memo(ctx, field) +func (ec *executionContext) _BlockListEdge_block(ctx context.Context, field graphql.CollectedField, obj *model.BlockListEdge) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockListEdge_block(ctx, field) if err != nil { return graphql.Null } @@ -2021,7 +2189,7 @@ func (ec *executionContext) _BlockTransaction_memo(ctx context.Context, field gr }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Memo, nil + return obj.Block, nil }) if err != nil { ec.Error(ctx, err) @@ -2033,26 +2201,62 @@ func (ec *executionContext) _BlockTransaction_memo(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*model.Block) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNBlock2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlock(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_BlockTransaction_memo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockListEdge_block(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "BlockTransaction", + Object: "BlockListEdge", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "hash": + return ec.fieldContext_Block_hash(ctx, field) + case "height": + return ec.fieldContext_Block_height(ctx, field) + case "version": + return ec.fieldContext_Block_version(ctx, field) + case "chain_id": + return ec.fieldContext_Block_chain_id(ctx, field) + case "time": + return ec.fieldContext_Block_time(ctx, field) + case "num_txs": + return ec.fieldContext_Block_num_txs(ctx, field) + case "total_txs": + return ec.fieldContext_Block_total_txs(ctx, field) + case "app_version": + return ec.fieldContext_Block_app_version(ctx, field) + case "last_block_hash": + return ec.fieldContext_Block_last_block_hash(ctx, field) + case "last_commit_hash": + return ec.fieldContext_Block_last_commit_hash(ctx, field) + case "validators_hash": + return ec.fieldContext_Block_validators_hash(ctx, field) + case "next_validators_hash": + return ec.fieldContext_Block_next_validators_hash(ctx, field) + case "consensus_hash": + return ec.fieldContext_Block_consensus_hash(ctx, field) + case "app_hash": + return ec.fieldContext_Block_app_hash(ctx, field) + case "last_results_hash": + return ec.fieldContext_Block_last_results_hash(ctx, field) + case "proposer_address_raw": + return ec.fieldContext_Block_proposer_address_raw(ctx, field) + case "txs": + return ec.fieldContext_Block_txs(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Block", field.Name) }, } return fc, nil } -func (ec *executionContext) _BlockTransaction_content_raw(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_BlockTransaction_content_raw(ctx, field) +func (ec *executionContext) _BlockListEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *model.BlockListEdge) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockListEdge_cursor(ctx, field) if err != nil { return graphql.Null } @@ -2065,7 +2269,7 @@ func (ec *executionContext) _BlockTransaction_content_raw(ctx context.Context, f }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ContentRaw, nil + return obj.Cursor, nil }) if err != nil { ec.Error(ctx, err) @@ -2077,26 +2281,26 @@ func (ec *executionContext) _BlockTransaction_content_raw(ctx context.Context, f } return graphql.Null } - res := resTmp.(string) + res := resTmp.(model.Cursor) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNCursor2githubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_BlockTransaction_content_raw(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockListEdge_cursor(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "BlockTransaction", + Object: "BlockListEdge", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Cursor does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Coin_amount(ctx context.Context, field graphql.CollectedField, obj *model.Coin) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Coin_amount(ctx, field) +func (ec *executionContext) _BlockTransaction_hash(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockTransaction_hash(ctx, field) if err != nil { return graphql.Null } @@ -2109,7 +2313,7 @@ func (ec *executionContext) _Coin_amount(ctx context.Context, field graphql.Coll }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Amount, nil + return obj.Hash, nil }) if err != nil { ec.Error(ctx, err) @@ -2121,26 +2325,26 @@ func (ec *executionContext) _Coin_amount(ctx context.Context, field graphql.Coll } return graphql.Null } - res := resTmp.(int) + res := resTmp.(string) fc.Result = res - return ec.marshalNInt2int(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Coin_amount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockTransaction_hash(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Coin", + Object: "BlockTransaction", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type Int does not have child fields") + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _Coin_denom(ctx context.Context, field graphql.CollectedField, obj *model.Coin) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Coin_denom(ctx, field) +func (ec *executionContext) _BlockTransaction_fee(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockTransaction_fee(ctx, field) if err != nil { return graphql.Null } @@ -2153,7 +2357,7 @@ func (ec *executionContext) _Coin_denom(ctx context.Context, field graphql.Colle }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Denom, nil + return obj.Fee, nil }) if err != nil { ec.Error(ctx, err) @@ -2165,26 +2369,32 @@ func (ec *executionContext) _Coin_denom(ctx context.Context, field graphql.Colle } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*model.TxFee) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNTxFee2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTxFee(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Coin_denom(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockTransaction_fee(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Coin", + Object: "BlockTransaction", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "gas_wanted": + return ec.fieldContext_TxFee_gas_wanted(ctx, field) + case "gas_fee": + return ec.fieldContext_TxFee_gas_fee(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TxFee", field.Name) }, } return fc, nil } -func (ec *executionContext) _GnoEvent_type(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_GnoEvent_type(ctx, field) +func (ec *executionContext) _BlockTransaction_memo(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockTransaction_memo(ctx, field) if err != nil { return graphql.Null } @@ -2197,7 +2407,7 @@ func (ec *executionContext) _GnoEvent_type(ctx context.Context, field graphql.Co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Type, nil + return obj.Memo, nil }) if err != nil { ec.Error(ctx, err) @@ -2214,9 +2424,9 @@ func (ec *executionContext) _GnoEvent_type(ctx context.Context, field graphql.Co return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GnoEvent_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockTransaction_memo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "GnoEvent", + Object: "BlockTransaction", Field: field, IsMethod: false, IsResolver: false, @@ -2227,8 +2437,8 @@ func (ec *executionContext) fieldContext_GnoEvent_type(ctx context.Context, fiel return fc, nil } -func (ec *executionContext) _GnoEvent_pkg_path(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_GnoEvent_pkg_path(ctx, field) +func (ec *executionContext) _BlockTransaction_content_raw(ctx context.Context, field graphql.CollectedField, obj *model.BlockTransaction) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_BlockTransaction_content_raw(ctx, field) if err != nil { return graphql.Null } @@ -2241,7 +2451,7 @@ func (ec *executionContext) _GnoEvent_pkg_path(ctx context.Context, field graphq }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.PkgPath, nil + return obj.ContentRaw, nil }) if err != nil { ec.Error(ctx, err) @@ -2258,9 +2468,9 @@ func (ec *executionContext) _GnoEvent_pkg_path(ctx context.Context, field graphq return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GnoEvent_pkg_path(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_BlockTransaction_content_raw(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "GnoEvent", + Object: "BlockTransaction", Field: field, IsMethod: false, IsResolver: false, @@ -2271,8 +2481,8 @@ func (ec *executionContext) fieldContext_GnoEvent_pkg_path(ctx context.Context, return fc, nil } -func (ec *executionContext) _GnoEvent_func(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_GnoEvent_func(ctx, field) +func (ec *executionContext) _Coin_amount(ctx context.Context, field graphql.CollectedField, obj *model.Coin) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Coin_amount(ctx, field) if err != nil { return graphql.Null } @@ -2285,7 +2495,7 @@ func (ec *executionContext) _GnoEvent_func(ctx context.Context, field graphql.Co }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Func, nil + return obj.Amount, nil }) if err != nil { ec.Error(ctx, err) @@ -2297,26 +2507,26 @@ func (ec *executionContext) _GnoEvent_func(ctx context.Context, field graphql.Co } return graphql.Null } - res := resTmp.(string) + res := resTmp.(int) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNInt2int(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GnoEvent_func(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Coin_amount(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "GnoEvent", + Object: "Coin", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + return nil, errors.New("field of type Int does not have child fields") }, } return fc, nil } -func (ec *executionContext) _GnoEvent_attrs(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_GnoEvent_attrs(ctx, field) +func (ec *executionContext) _Coin_denom(ctx context.Context, field graphql.CollectedField, obj *model.Coin) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Coin_denom(ctx, field) if err != nil { return graphql.Null } @@ -2329,42 +2539,218 @@ func (ec *executionContext) _GnoEvent_attrs(ctx context.Context, field graphql.C }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Attrs, nil + return obj.Denom, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*model.GnoEventAttribute) + res := resTmp.(string) fc.Result = res - return ec.marshalOGnoEventAttribute2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐGnoEventAttributeᚄ(ctx, field.Selections, res) + return ec.marshalNString2string(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_GnoEvent_attrs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_Coin_denom(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "GnoEvent", + Object: "Coin", Field: field, IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "key": - return ec.fieldContext_GnoEventAttribute_key(ctx, field) - case "value": - return ec.fieldContext_GnoEventAttribute_value(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type GnoEventAttribute", field.Name) + return nil, errors.New("field of type String does not have child fields") }, } return fc, nil } -func (ec *executionContext) _GnoEventAttribute_key(ctx context.Context, field graphql.CollectedField, obj *model.GnoEventAttribute) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_GnoEventAttribute_key(ctx, field) - if err != nil { +func (ec *executionContext) _GnoEvent_type(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GnoEvent_type(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Type, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GnoEvent_type(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GnoEvent", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _GnoEvent_pkg_path(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GnoEvent_pkg_path(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.PkgPath, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GnoEvent_pkg_path(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GnoEvent", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _GnoEvent_func(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GnoEvent_func(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Func, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GnoEvent_func(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GnoEvent", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _GnoEvent_attrs(ctx context.Context, field graphql.CollectedField, obj *model.GnoEvent) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GnoEvent_attrs(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Attrs, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]*model.GnoEventAttribute) + fc.Result = res + return ec.marshalOGnoEventAttribute2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐGnoEventAttributeᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_GnoEvent_attrs(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "GnoEvent", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "key": + return ec.fieldContext_GnoEventAttribute_key(ctx, field) + case "value": + return ec.fieldContext_GnoEventAttribute_value(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type GnoEventAttribute", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _GnoEventAttribute_key(ctx context.Context, field graphql.CollectedField, obj *model.GnoEventAttribute) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_GnoEventAttribute_key(ctx, field) + if err != nil { return graphql.Null } ctx = graphql.WithFieldContext(ctx, fc) @@ -3170,8 +3556,8 @@ func (ec *executionContext) fieldContext_MsgRun_package(ctx context.Context, fie return fc, nil } -func (ec *executionContext) _Query_transactions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_transactions(ctx, field) +func (ec *executionContext) _PageInfo_first(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PageInfo_first(ctx, field) if err != nil { return graphql.Null } @@ -3184,7 +3570,7 @@ func (ec *executionContext) _Query_transactions(ctx context.Context, field graph }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Transactions(rctx, fc.Args["filter"].(model.TransactionFilter)) + return obj.First, nil }) if err != nil { ec.Error(ctx, err) @@ -3193,61 +3579,67 @@ func (ec *executionContext) _Query_transactions(ctx context.Context, field graph if resTmp == nil { return graphql.Null } - res := resTmp.([]*model.Transaction) + res := resTmp.(*model.Cursor) fc.Result = res - return ec.marshalOTransaction2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionᚄ(ctx, field.Selections, res) + return ec.marshalOCursor2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_transactions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PageInfo_first(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Query", + Object: "PageInfo", Field: field, - IsMethod: true, - IsResolver: true, + IsMethod: false, + IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "index": - return ec.fieldContext_Transaction_index(ctx, field) - case "hash": - return ec.fieldContext_Transaction_hash(ctx, field) - case "success": - return ec.fieldContext_Transaction_success(ctx, field) - case "block_height": - return ec.fieldContext_Transaction_block_height(ctx, field) - case "gas_wanted": - return ec.fieldContext_Transaction_gas_wanted(ctx, field) - case "gas_used": - return ec.fieldContext_Transaction_gas_used(ctx, field) - case "gas_fee": - return ec.fieldContext_Transaction_gas_fee(ctx, field) - case "content_raw": - return ec.fieldContext_Transaction_content_raw(ctx, field) - case "messages": - return ec.fieldContext_Transaction_messages(ctx, field) - case "memo": - return ec.fieldContext_Transaction_memo(ctx, field) - case "response": - return ec.fieldContext_Transaction_response(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type Transaction", field.Name) + return nil, errors.New("field of type Cursor does not have child fields") }, } + return fc, nil +} + +func (ec *executionContext) _PageInfo_last(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PageInfo_last(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) defer func() { if r := recover(); r != nil { - err = ec.Recover(ctx, r) - ec.Error(ctx, err) + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null } }() - ctx = graphql.WithFieldContext(ctx, fc) - if fc.Args, err = ec.field_Query_transactions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Last, nil + }) + if err != nil { ec.Error(ctx, err) - return fc, err + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*model.Cursor) + fc.Result = res + return ec.marshalOCursor2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_PageInfo_last(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "PageInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Cursor does not have child fields") + }, } return fc, nil } -func (ec *executionContext) _Query_blocks(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Query_blocks(ctx, field) +func (ec *executionContext) _PageInfo_hasNext(ctx context.Context, field graphql.CollectedField, obj *model.PageInfo) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_PageInfo_hasNext(ctx, field) if err != nil { return graphql.Null } @@ -3260,64 +3652,142 @@ func (ec *executionContext) _Query_blocks(ctx context.Context, field graphql.Col }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().Blocks(rctx, fc.Args["filter"].(model.BlockFilter)) + return obj.HasNext, nil }) if err != nil { ec.Error(ctx, err) return graphql.Null } if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } return graphql.Null } - res := resTmp.([]*model.Block) + res := resTmp.(bool) fc.Result = res - return ec.marshalOBlock2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockᚄ(ctx, field.Selections, res) + return ec.marshalNBoolean2bool(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Query_blocks(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_PageInfo_hasNext(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Query", + Object: "PageInfo", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type Boolean does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Query_transactions(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_transactions(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Transactions(rctx, fc.Args["filter"].(model.TransactionFilter), fc.Args["after"].(*model.Cursor), fc.Args["size"].(*int), fc.Args["ascending"].(bool)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.TransactionList) + fc.Result = res + return ec.marshalNTransactionList2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionList(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_transactions(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", Field: field, IsMethod: true, IsResolver: true, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "hash": - return ec.fieldContext_Block_hash(ctx, field) - case "height": - return ec.fieldContext_Block_height(ctx, field) - case "version": - return ec.fieldContext_Block_version(ctx, field) - case "chain_id": - return ec.fieldContext_Block_chain_id(ctx, field) - case "time": - return ec.fieldContext_Block_time(ctx, field) - case "num_txs": - return ec.fieldContext_Block_num_txs(ctx, field) - case "total_txs": - return ec.fieldContext_Block_total_txs(ctx, field) - case "app_version": - return ec.fieldContext_Block_app_version(ctx, field) - case "last_block_hash": - return ec.fieldContext_Block_last_block_hash(ctx, field) - case "last_commit_hash": - return ec.fieldContext_Block_last_commit_hash(ctx, field) - case "validators_hash": - return ec.fieldContext_Block_validators_hash(ctx, field) - case "next_validators_hash": - return ec.fieldContext_Block_next_validators_hash(ctx, field) - case "consensus_hash": - return ec.fieldContext_Block_consensus_hash(ctx, field) - case "app_hash": - return ec.fieldContext_Block_app_hash(ctx, field) - case "last_results_hash": - return ec.fieldContext_Block_last_results_hash(ctx, field) - case "proposer_address_raw": - return ec.fieldContext_Block_proposer_address_raw(ctx, field) - case "txs": - return ec.fieldContext_Block_txs(ctx, field) + case "edges": + return ec.fieldContext_TransactionList_edges(ctx, field) + case "pageInfo": + return ec.fieldContext_TransactionList_pageInfo(ctx, field) } - return nil, fmt.Errorf("no field named %q was found under type Block", field.Name) + return nil, fmt.Errorf("no field named %q was found under type TransactionList", field.Name) + }, + } + defer func() { + if r := recover(); r != nil { + err = ec.Recover(ctx, r) + ec.Error(ctx, err) + } + }() + ctx = graphql.WithFieldContext(ctx, fc) + if fc.Args, err = ec.field_Query_transactions_args(ctx, field.ArgumentMap(ec.Variables)); err != nil { + ec.Error(ctx, err) + return fc, err + } + return fc, nil +} + +func (ec *executionContext) _Query_blocks(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Query_blocks(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().Blocks(rctx, fc.Args["filter"].(model.BlockFilter), fc.Args["after"].(*model.Cursor), fc.Args["size"].(*int), fc.Args["ascending"].(bool)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.BlockList) + fc.Result = res + return ec.marshalNBlockList2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockList(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Query_blocks(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Query", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "edges": + return ec.fieldContext_BlockList_edges(ctx, field) + case "pageInfo": + return ec.fieldContext_BlockList_pageInfo(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type BlockList", field.Name) }, } defer func() { @@ -4030,7 +4500,203 @@ func (ec *executionContext) _Transaction_content_raw(ctx context.Context, field }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.ContentRaw(), nil + return obj.ContentRaw(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Transaction_content_raw(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Transaction", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Transaction_messages(ctx context.Context, field graphql.CollectedField, obj *model.Transaction) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Transaction_messages(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Messages(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]*model.TransactionMessage) + fc.Result = res + return ec.marshalNTransactionMessage2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionMessage(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Transaction_messages(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Transaction", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "typeUrl": + return ec.fieldContext_TransactionMessage_typeUrl(ctx, field) + case "route": + return ec.fieldContext_TransactionMessage_route(ctx, field) + case "value": + return ec.fieldContext_TransactionMessage_value(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TransactionMessage", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _Transaction_memo(ctx context.Context, field graphql.CollectedField, obj *model.Transaction) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Transaction_memo(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Memo(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNString2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Transaction_memo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Transaction", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type String does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _Transaction_response(ctx context.Context, field graphql.CollectedField, obj *model.Transaction) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Transaction_response(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Response(), nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*model.TransactionResponse) + fc.Result = res + return ec.marshalNTransactionResponse2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionResponse(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Transaction_response(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Transaction", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "log": + return ec.fieldContext_TransactionResponse_log(ctx, field) + case "info": + return ec.fieldContext_TransactionResponse_info(ctx, field) + case "error": + return ec.fieldContext_TransactionResponse_error(ctx, field) + case "data": + return ec.fieldContext_TransactionResponse_data(ctx, field) + case "events": + return ec.fieldContext_TransactionResponse_events(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TransactionResponse", field.Name) + }, + } + return fc, nil +} + +func (ec *executionContext) _TransactionList_edges(ctx context.Context, field graphql.CollectedField, obj *model.TransactionList) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionList_edges(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Edges, nil }) if err != nil { ec.Error(ctx, err) @@ -4042,26 +4708,32 @@ func (ec *executionContext) _Transaction_content_raw(ctx context.Context, field } return graphql.Null } - res := resTmp.(string) + res := resTmp.([]*model.TransactionListEdge) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNTransactionListEdge2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionListEdgeᚄ(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Transaction_content_raw(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TransactionList_edges(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Transaction", + Object: "TransactionList", Field: field, - IsMethod: true, + IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "transaction": + return ec.fieldContext_TransactionListEdge_transaction(ctx, field) + case "cursor": + return ec.fieldContext_TransactionListEdge_cursor(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TransactionListEdge", field.Name) }, } return fc, nil } -func (ec *executionContext) _Transaction_messages(ctx context.Context, field graphql.CollectedField, obj *model.Transaction) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Transaction_messages(ctx, field) +func (ec *executionContext) _TransactionList_pageInfo(ctx context.Context, field graphql.CollectedField, obj *model.TransactionList) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionList_pageInfo(ctx, field) if err != nil { return graphql.Null } @@ -4074,7 +4746,7 @@ func (ec *executionContext) _Transaction_messages(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Messages(), nil + return obj.PageInfo, nil }) if err != nil { ec.Error(ctx, err) @@ -4086,34 +4758,34 @@ func (ec *executionContext) _Transaction_messages(ctx context.Context, field gra } return graphql.Null } - res := resTmp.([]*model.TransactionMessage) + res := resTmp.(*model.PageInfo) fc.Result = res - return ec.marshalNTransactionMessage2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionMessage(ctx, field.Selections, res) + return ec.marshalNPageInfo2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐPageInfo(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Transaction_messages(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TransactionList_pageInfo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Transaction", + Object: "TransactionList", Field: field, - IsMethod: true, + IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { switch field.Name { - case "typeUrl": - return ec.fieldContext_TransactionMessage_typeUrl(ctx, field) - case "route": - return ec.fieldContext_TransactionMessage_route(ctx, field) - case "value": - return ec.fieldContext_TransactionMessage_value(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type TransactionMessage", field.Name) + case "first": + return ec.fieldContext_PageInfo_first(ctx, field) + case "last": + return ec.fieldContext_PageInfo_last(ctx, field) + case "hasNext": + return ec.fieldContext_PageInfo_hasNext(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type PageInfo", field.Name) }, } return fc, nil } -func (ec *executionContext) _Transaction_memo(ctx context.Context, field graphql.CollectedField, obj *model.Transaction) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Transaction_memo(ctx, field) +func (ec *executionContext) _TransactionListEdge_transaction(ctx context.Context, field graphql.CollectedField, obj *model.TransactionListEdge) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionListEdge_transaction(ctx, field) if err != nil { return graphql.Null } @@ -4126,7 +4798,7 @@ func (ec *executionContext) _Transaction_memo(ctx context.Context, field graphql }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Memo(), nil + return obj.Transaction, nil }) if err != nil { ec.Error(ctx, err) @@ -4138,26 +4810,50 @@ func (ec *executionContext) _Transaction_memo(ctx context.Context, field graphql } return graphql.Null } - res := resTmp.(string) + res := resTmp.(*model.Transaction) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNTransaction2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransaction(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Transaction_memo(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TransactionListEdge_transaction(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Transaction", + Object: "TransactionListEdge", Field: field, - IsMethod: true, + IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - return nil, errors.New("field of type String does not have child fields") + switch field.Name { + case "index": + return ec.fieldContext_Transaction_index(ctx, field) + case "hash": + return ec.fieldContext_Transaction_hash(ctx, field) + case "success": + return ec.fieldContext_Transaction_success(ctx, field) + case "block_height": + return ec.fieldContext_Transaction_block_height(ctx, field) + case "gas_wanted": + return ec.fieldContext_Transaction_gas_wanted(ctx, field) + case "gas_used": + return ec.fieldContext_Transaction_gas_used(ctx, field) + case "gas_fee": + return ec.fieldContext_Transaction_gas_fee(ctx, field) + case "content_raw": + return ec.fieldContext_Transaction_content_raw(ctx, field) + case "messages": + return ec.fieldContext_Transaction_messages(ctx, field) + case "memo": + return ec.fieldContext_Transaction_memo(ctx, field) + case "response": + return ec.fieldContext_Transaction_response(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Transaction", field.Name) }, } return fc, nil } -func (ec *executionContext) _Transaction_response(ctx context.Context, field graphql.CollectedField, obj *model.Transaction) (ret graphql.Marshaler) { - fc, err := ec.fieldContext_Transaction_response(ctx, field) +func (ec *executionContext) _TransactionListEdge_cursor(ctx context.Context, field graphql.CollectedField, obj *model.TransactionListEdge) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionListEdge_cursor(ctx, field) if err != nil { return graphql.Null } @@ -4170,7 +4866,7 @@ func (ec *executionContext) _Transaction_response(ctx context.Context, field gra }() resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return obj.Response(), nil + return obj.Cursor, nil }) if err != nil { ec.Error(ctx, err) @@ -4182,31 +4878,19 @@ func (ec *executionContext) _Transaction_response(ctx context.Context, field gra } return graphql.Null } - res := resTmp.(*model.TransactionResponse) + res := resTmp.(model.Cursor) fc.Result = res - return ec.marshalNTransactionResponse2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionResponse(ctx, field.Selections, res) + return ec.marshalNCursor2githubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx, field.Selections, res) } -func (ec *executionContext) fieldContext_Transaction_response(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { +func (ec *executionContext) fieldContext_TransactionListEdge_cursor(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { fc = &graphql.FieldContext{ - Object: "Transaction", + Object: "TransactionListEdge", Field: field, - IsMethod: true, + IsMethod: false, IsResolver: false, Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { - switch field.Name { - case "log": - return ec.fieldContext_TransactionResponse_log(ctx, field) - case "info": - return ec.fieldContext_TransactionResponse_info(ctx, field) - case "error": - return ec.fieldContext_TransactionResponse_error(ctx, field) - case "data": - return ec.fieldContext_TransactionResponse_data(ctx, field) - case "events": - return ec.fieldContext_TransactionResponse_events(ctx, field) - } - return nil, fmt.Errorf("no field named %q was found under type TransactionResponse", field.Name) + return nil, errors.New("field of type Cursor does not have child fields") }, } return fc, nil @@ -7410,6 +8094,94 @@ func (ec *executionContext) _Block(ctx context.Context, sel ast.SelectionSet, ob return out } +var blockListImplementors = []string{"BlockList"} + +func (ec *executionContext) _BlockList(ctx context.Context, sel ast.SelectionSet, obj *model.BlockList) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, blockListImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("BlockList") + case "edges": + out.Values[i] = ec._BlockList_edges(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._BlockList_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var blockListEdgeImplementors = []string{"BlockListEdge"} + +func (ec *executionContext) _BlockListEdge(ctx context.Context, sel ast.SelectionSet, obj *model.BlockListEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, blockListEdgeImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("BlockListEdge") + case "block": + out.Values[i] = ec._BlockListEdge_block(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "cursor": + out.Values[i] = ec._BlockListEdge_cursor(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var blockTransactionImplementors = []string{"BlockTransaction"} func (ec *executionContext) _BlockTransaction(ctx context.Context, sel ast.SelectionSet, obj *model.BlockTransaction) graphql.Marshaler { @@ -7847,6 +8619,49 @@ func (ec *executionContext) _MsgRun(ctx context.Context, sel ast.SelectionSet, o return out } +var pageInfoImplementors = []string{"PageInfo"} + +func (ec *executionContext) _PageInfo(ctx context.Context, sel ast.SelectionSet, obj *model.PageInfo) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, pageInfoImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("PageInfo") + case "first": + out.Values[i] = ec._PageInfo_first(ctx, field, obj) + case "last": + out.Values[i] = ec._PageInfo_last(ctx, field, obj) + case "hasNext": + out.Values[i] = ec._PageInfo_hasNext(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var queryImplementors = []string{"Query"} func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) graphql.Marshaler { @@ -7876,6 +8691,9 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } }() res = ec._Query_transactions(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -7895,6 +8713,9 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } }() res = ec._Query_blocks(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } return res } @@ -8037,8 +8858,96 @@ func (ec *executionContext) _Transaction(ctx context.Context, sel ast.SelectionS if out.Values[i] == graphql.Null { out.Invalids++ } - case "response": - out.Values[i] = ec._Transaction_response(ctx, field, obj) + case "response": + out.Values[i] = ec._Transaction_response(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var transactionListImplementors = []string{"TransactionList"} + +func (ec *executionContext) _TransactionList(ctx context.Context, sel ast.SelectionSet, obj *model.TransactionList) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, transactionListImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TransactionList") + case "edges": + out.Values[i] = ec._TransactionList_edges(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "pageInfo": + out.Values[i] = ec._TransactionList_pageInfo(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + +var transactionListEdgeImplementors = []string{"TransactionListEdge"} + +func (ec *executionContext) _TransactionListEdge(ctx context.Context, sel ast.SelectionSet, obj *model.TransactionListEdge) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, transactionListEdgeImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TransactionListEdge") + case "transaction": + out.Values[i] = ec._TransactionListEdge_transaction(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "cursor": + out.Values[i] = ec._TransactionListEdge_cursor(ctx, field, obj) if out.Values[i] == graphql.Null { out.Invalids++ } @@ -8637,6 +9546,74 @@ func (ec *executionContext) unmarshalNBlockFilter2githubᚗcomᚋgnolangᚋtxᚑ return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNBlockList2githubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockList(ctx context.Context, sel ast.SelectionSet, v model.BlockList) graphql.Marshaler { + return ec._BlockList(ctx, sel, &v) +} + +func (ec *executionContext) marshalNBlockList2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockList(ctx context.Context, sel ast.SelectionSet, v *model.BlockList) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._BlockList(ctx, sel, v) +} + +func (ec *executionContext) marshalNBlockListEdge2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockListEdgeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.BlockListEdge) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNBlockListEdge2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockListEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNBlockListEdge2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockListEdge(ctx context.Context, sel ast.SelectionSet, v *model.BlockListEdge) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._BlockListEdge(ctx, sel, v) +} + func (ec *executionContext) marshalNBlockTransaction2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockTransaction(ctx context.Context, sel ast.SelectionSet, v []*model.BlockTransaction) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -8700,6 +9677,22 @@ func (ec *executionContext) marshalNCoin2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexe return ec._Coin(ctx, sel, v) } +func (ec *executionContext) unmarshalNCursor2githubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx context.Context, v interface{}) (model.Cursor, error) { + tmp, err := graphql.UnmarshalString(v) + res := model.Cursor(tmp) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNCursor2githubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx context.Context, sel ast.SelectionSet, v model.Cursor) graphql.Marshaler { + res := graphql.MarshalString(string(v)) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + } + return res +} + func (ec *executionContext) unmarshalNEventAttributeInput2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐEventAttributeInput(ctx context.Context, v interface{}) (*model.EventAttributeInput, error) { res, err := ec.unmarshalInputEventAttributeInput(ctx, v) return &res, graphql.ErrorOnPath(ctx, err) @@ -8780,6 +9773,16 @@ func (ec *executionContext) marshalNMessageValue2githubᚗcomᚋgnolangᚋtxᚑi return ec._MessageValue(ctx, sel, v) } +func (ec *executionContext) marshalNPageInfo2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐPageInfo(ctx context.Context, sel ast.SelectionSet, v *model.PageInfo) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._PageInfo(ctx, sel, v) +} + func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.ErrorOnPath(ctx, err) @@ -8829,6 +9832,74 @@ func (ec *executionContext) unmarshalNTransactionFilter2githubᚗcomᚋgnolang return res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalNTransactionList2githubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionList(ctx context.Context, sel ast.SelectionSet, v model.TransactionList) graphql.Marshaler { + return ec._TransactionList(ctx, sel, &v) +} + +func (ec *executionContext) marshalNTransactionList2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionList(ctx context.Context, sel ast.SelectionSet, v *model.TransactionList) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._TransactionList(ctx, sel, v) +} + +func (ec *executionContext) marshalNTransactionListEdge2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionListEdgeᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.TransactionListEdge) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNTransactionListEdge2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionListEdge(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNTransactionListEdge2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionListEdge(ctx context.Context, sel ast.SelectionSet, v *model.TransactionListEdge) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "the requested element is null which the schema does not allow") + } + return graphql.Null + } + return ec._TransactionListEdge(ctx, sel, v) +} + func (ec *executionContext) marshalNTransactionMessage2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionMessage(ctx context.Context, sel ast.SelectionSet, v []*model.TransactionMessage) graphql.Marshaler { ret := make(graphql.Array, len(v)) var wg sync.WaitGroup @@ -9156,53 +10227,6 @@ func (ec *executionContext) unmarshalOBankMsgSendInput2ᚖgithubᚗcomᚋgnolang return &res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalOBlock2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Block) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNBlock2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlock(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret -} - func (ec *executionContext) marshalOBlockTransaction2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐBlockTransaction(ctx context.Context, sel ast.SelectionSet, v *model.BlockTransaction) graphql.Marshaler { if v == nil { return graphql.Null @@ -9243,6 +10267,23 @@ func (ec *executionContext) marshalOCoin2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexe return ec._Coin(ctx, sel, v) } +func (ec *executionContext) unmarshalOCursor2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx context.Context, v interface{}) (*model.Cursor, error) { + if v == nil { + return nil, nil + } + tmp, err := graphql.UnmarshalString(v) + res := model.Cursor(tmp) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOCursor2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐCursor(ctx context.Context, sel ast.SelectionSet, v *model.Cursor) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalString(string(*v)) + return res +} + func (ec *executionContext) marshalOEvent2githubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐEvent(ctx context.Context, sel ast.SelectionSet, v model.Event) graphql.Marshaler { if v == nil { return graphql.Null @@ -9603,53 +10644,6 @@ func (ec *executionContext) marshalOTime2ᚖtimeᚐTime(ctx context.Context, sel return res } -func (ec *executionContext) marshalOTransaction2ᚕᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionᚄ(ctx context.Context, sel ast.SelectionSet, v []*model.Transaction) graphql.Marshaler { - if v == nil { - return graphql.Null - } - ret := make(graphql.Array, len(v)) - var wg sync.WaitGroup - isLen1 := len(v) == 1 - if !isLen1 { - wg.Add(len(v)) - } - for i := range v { - i := i - fc := &graphql.FieldContext{ - Index: &i, - Result: &v[i], - } - ctx := graphql.WithFieldContext(ctx, fc) - f := func(i int) { - defer func() { - if r := recover(); r != nil { - ec.Error(ctx, ec.Recover(ctx, r)) - ret = nil - } - }() - if !isLen1 { - defer wg.Done() - } - ret[i] = ec.marshalNTransaction2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransaction(ctx, sel, v[i]) - } - if isLen1 { - f(i) - } else { - go f(i) - } - - } - wg.Wait() - - for _, e := range ret { - if e == graphql.Null { - return graphql.Null - } - } - - return ret -} - func (ec *executionContext) unmarshalOTransactionBankMessageInput2ᚖgithubᚗcomᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionBankMessageInput(ctx context.Context, v interface{}) (*model.TransactionBankMessageInput, error) { if v == nil { return nil, nil diff --git a/serve/graph/model/block_list.go b/serve/graph/model/block_list.go new file mode 100644 index 00000000..bdbbc334 --- /dev/null +++ b/serve/graph/model/block_list.go @@ -0,0 +1,23 @@ +package model + +func NewBlockList(edges []*BlockListEdge, hasNext bool) *BlockList { + pageInfo := NewPageInfo(nil, nil, hasNext) + + if len(edges) > 0 { + first := edges[0] + last := edges[len(edges)-1] + pageInfo = NewPageInfo(&first.Cursor, &last.Cursor, hasNext) + } + + return &BlockList{ + PageInfo: pageInfo, + Edges: edges, + } +} + +func NewBlockListEdge(block *Block) *BlockListEdge { + return &BlockListEdge{ + Cursor: NewCursor(block.ID()), + Block: block, + } +} diff --git a/serve/graph/model/cursor.go b/serve/graph/model/cursor.go new file mode 100644 index 00000000..949a0b04 --- /dev/null +++ b/serve/graph/model/cursor.go @@ -0,0 +1,101 @@ +package model + +import ( + "encoding/base64" + "errors" + "strconv" + "strings" +) + +// Cursor represents a string key of an element position in a sequential list of edges. +type Cursor string + +// Create a cursor by base64-encoding the ID. +func NewCursor(id string) Cursor { + return Cursor(base64.StdEncoding.EncodeToString([]byte(id))) +} + +// UnmarshalGraphQL unmarshal incoming cursor into a local variable. +func (c *Cursor) UnmarshalGraphQL(input interface{}) error { + var err error + + switch input := input.(type) { + case string: + *c = Cursor(input) + case int32: + *c = Cursor(strconv.Itoa(int(input))) + default: + err = errors.New("wrong cursor type") + } + + return err +} + +// MarshalJSON encodes a cursor to JSON for transport. +func (c Cursor) MarshalJSON() ([]byte, error) { + return strconv.AppendQuote(nil, string(c)), nil +} + +// Decodes and returns the base64-encoded ID, which is the value of the cursor. +func (c *Cursor) ID() (string, error) { + if c == nil { + return "", nil + } + + base64Str := string(*c) + + decoded, err := base64.StdEncoding.DecodeString(base64Str) + if err != nil { + return "", err + } + + return string(decoded), nil +} + +// Get the block height from the ID of the Cursor. +func (c *Cursor) BlockHeight() (uint64, error) { + id, err := c.ID() + if err != nil { + return 0, err + } + + if id == "" { + return 0, nil + } + + blockHeight, err := strconv.ParseUint(id, 0, 64) + if err != nil { + return 0, err + } + + return blockHeight, nil +} + +// Get the values of block height and transaction index by the ID of the Cursor. +func (c *Cursor) BlockHeightWithIndex() (uint64, uint32, error) { + id, err := c.ID() + if err != nil { + return 0, 0, err + } + + if id == "" { + return 0, 0, nil + } + + afterParams := strings.Split(id, "_") + if len(afterParams) < 2 { + return 0, 0, errors.New("wrong cursor type") + } + + blockHeight, err := strconv.ParseUint(afterParams[0], 0, 64) + if err != nil { + return 0, 0, err + } + + index, err := strconv.ParseUint(afterParams[1], 0, 32) + if err != nil { + return 0, 0, err + } + + return blockHeight, uint32(index), nil +} diff --git a/serve/graph/model/models_gen.go b/serve/graph/model/models_gen.go index e3e953cb..8fbbaf6b 100644 --- a/serve/graph/model/models_gen.go +++ b/serve/graph/model/models_gen.go @@ -71,6 +71,20 @@ type BlockFilter struct { ToTime *time.Time `json:"to_time,omitempty"` } +// BlockList is a list of block edges provided by sequential access request. +type BlockList struct { + // Edges contains provided edges of the sequential list. + Edges []*BlockListEdge `json:"edges"` + // PageInfo is an information about the current page of block edges. + PageInfo *PageInfo `json:"pageInfo"` +} + +// BlockListEdge is a single edge in a sequential list of blocks. +type BlockListEdge struct { + Block *Block `json:"block"` + Cursor Cursor `json:"cursor"` +} + // Defines a transaction within a block, its execution specifics and content. type BlockTransaction struct { // Hash computes the TMHASH hash of the wire encoded transaction. @@ -272,6 +286,16 @@ type MsgRunInput struct { Package *MemPackageInput `json:"package,omitempty"` } +// PageInfo contains information about a sequential access list page. +type PageInfo struct { + // `first` is the cursor of the first edge of the edges list. null for empty list. + First *Cursor `json:"first,omitempty"` + // `last` if the cursor of the last edge of the edges list. null for empty list. + Last *Cursor `json:"last,omitempty"` + // `hasNext` specifies if there is another edge after the last one. + HasNext bool `json:"hasNext"` +} + // Root Query type to fetch data about Blocks and Transactions based on filters or retrieve the latest block height. type Query struct { } @@ -324,6 +348,18 @@ type TransactionFilter struct { Events []*EventInput `json:"events,omitempty"` } +// TransactionList is a list of transaction edges provided by sequential access request. +type TransactionList struct { + Edges []*TransactionListEdge `json:"edges"` + PageInfo *PageInfo `json:"pageInfo"` +} + +// TransactionListEdge is a single edge in a sequential list of transactions. +type TransactionListEdge struct { + Transaction *Transaction `json:"transaction"` + Cursor Cursor `json:"cursor"` +} + // Transaction's message to filter Transactions. // `TransactionMessageInput` can be configured as a filter with a transaction message's `router` and `type` and `parameters(bank / vm)`. type TransactionMessageInput struct { diff --git a/serve/graph/model/page_info.go b/serve/graph/model/page_info.go new file mode 100644 index 00000000..81cd5589 --- /dev/null +++ b/serve/graph/model/page_info.go @@ -0,0 +1,9 @@ +package model + +func NewPageInfo(first, last *Cursor, hasNext bool) *PageInfo { + return &PageInfo{ + First: first, + Last: last, + HasNext: hasNext, + } +} diff --git a/serve/graph/model/transaction_list.go b/serve/graph/model/transaction_list.go new file mode 100644 index 00000000..8e9dff74 --- /dev/null +++ b/serve/graph/model/transaction_list.go @@ -0,0 +1,23 @@ +package model + +func NewTransactionList(edges []*TransactionListEdge, hasNext bool) *TransactionList { + pageInfo := NewPageInfo(nil, nil, hasNext) + + if len(edges) > 0 { + first := edges[0] + last := edges[len(edges)-1] + pageInfo = NewPageInfo(&first.Cursor, &last.Cursor, hasNext) + } + + return &TransactionList{ + PageInfo: pageInfo, + Edges: edges, + } +} + +func NewTransactionListEdge(transaction *Transaction) *TransactionListEdge { + return &TransactionListEdge{ + Cursor: NewCursor(transaction.ID()), + Transaction: transaction, + } +} diff --git a/serve/graph/query.resolvers.go b/serve/graph/query.resolvers.go index 1abfb9a3..f7bb303a 100644 --- a/serve/graph/query.resolvers.go +++ b/serve/graph/query.resolvers.go @@ -13,96 +13,166 @@ import ( ) // Transactions is the resolver for the transactions field. -func (r *queryResolver) Transactions(ctx context.Context, filter model.TransactionFilter) ([]*model.Transaction, error) { +func (r *queryResolver) Transactions(ctx context.Context, filter model.TransactionFilter, after *model.Cursor, size *int, ascending bool) (*model.TransactionList, error) { if filter.Hash != nil { tx, err := r.store.GetTxByHash(*filter.Hash) if err != nil { return nil, gqlerror.Wrap(err) } - return []*model.Transaction{model.NewTransaction(tx)}, nil + + transactionListEdges := make([]*model.TransactionListEdge, 0) + transactionListEdges = append(transactionListEdges, model.NewTransactionListEdge(model.NewTransaction(tx))) + + return model.NewTransactionList(transactionListEdges, false), nil + } + + fromBlockHeight := uint64(deref(filter.FromBlockHeight)) + toBlockHeight := uint64(deref(filter.ToBlockHeight)) + fromIndex := uint32(deref(filter.FromIndex)) + toIndex := uint32(deref(filter.ToIndex)) + + afterBlockHeight, afterIndex, err := after.BlockHeightWithIndex() + if err != nil { + return nil, err + } + + // Adjusts the iterator range based on the value of after cursor. + if afterBlockHeight > 0 { + if ascending { + if fromBlockHeight <= afterBlockHeight { + fromBlockHeight = afterBlockHeight + 1 + fromIndex = uint32(afterIndex) + } + } else { + if toBlockHeight == 0 || toBlockHeight >= afterBlockHeight { + toBlockHeight = afterBlockHeight - 1 + toIndex = uint32(afterIndex) + } + } } it, err := r. store. TxIterator( - uint64(deref(filter.FromBlockHeight)), - uint64(deref(filter.ToBlockHeight)), - uint32(deref(filter.FromIndex)), - uint32(deref(filter.ToIndex)), + fromBlockHeight, + toBlockHeight, + fromIndex, + toIndex, + ascending, ) if err != nil { return nil, gqlerror.Wrap(err) } defer it.Close() - var out []*model.Transaction + transactions := make([]*model.TransactionListEdge, 0) + hasNext := true i := 0 + for { if i == maxElementsPerQuery { graphql.AddErrorf(ctx, "max elements per query reached (%d)", maxElementsPerQuery) - return out, nil + break + } + + if size != nil && deref(size) == i { + break } if !it.Next() { - return out, it.Error() + hasNext = false + err = it.Error() + break } select { case <-ctx.Done(): graphql.AddError(ctx, ctx.Err()) - return out, nil + return model.NewTransactionList(transactions, hasNext), nil default: t, err := it.Value() if err != nil { graphql.AddError(ctx, err) - return out, nil + return model.NewTransactionList(transactions, hasNext), err } transaction := model.NewTransaction(t) if !FilteredTransactionBy(transaction, filter) { continue } - out = append(out, transaction) + + transactions = append(transactions, model.NewTransactionListEdge(transaction)) i++ } } + + return model.NewTransactionList(transactions, hasNext), err } // Blocks is the resolver for the blocks field. -func (r *queryResolver) Blocks(ctx context.Context, filter model.BlockFilter) ([]*model.Block, error) { +func (r *queryResolver) Blocks(ctx context.Context, filter model.BlockFilter, after *model.Cursor, size *int, ascending bool) (*model.BlockList, error) { + fromBlockHeight := uint64(deref(filter.FromHeight)) + toBlockHeight := uint64(deref(filter.ToHeight)) + + afterBlockHeight, err := after.BlockHeight() + if err != nil { + return nil, err + } + + // Adjusts the iterator range based on the value of after cursor. + if afterBlockHeight > 0 { + if ascending { + if fromBlockHeight <= afterBlockHeight { + fromBlockHeight = afterBlockHeight + 1 + } + } else { + if toBlockHeight == 0 || toBlockHeight >= afterBlockHeight { + toBlockHeight = afterBlockHeight - 1 + } + } + } + it, err := r. store. BlockIterator( - uint64(deref(filter.FromHeight)), - uint64(deref(filter.ToHeight)), + fromBlockHeight, + toBlockHeight, + ascending, ) if err != nil { return nil, gqlerror.Wrap(err) } defer it.Close() - var out []*model.Block - + blocks := make([]*model.BlockListEdge, 0) + hasNext := true i := 0 + for { if i == maxElementsPerQuery { graphql.AddErrorf(ctx, "max elements per query reached (%d)", maxElementsPerQuery) - return out, nil + break + } + + if size != nil && deref(size) == i { + break } if !it.Next() { - return out, it.Error() + hasNext = false + err = it.Error() + break } select { case <-ctx.Done(): graphql.AddError(ctx, ctx.Err()) - return out, nil + return model.NewBlockList(blocks, hasNext), nil default: b, err := it.Value() if err != nil { graphql.AddError(ctx, err) - return out, nil + return model.NewBlockList(blocks, hasNext), err } block := model.NewBlock(b) @@ -110,10 +180,12 @@ func (r *queryResolver) Blocks(ctx context.Context, filter model.BlockFilter) ([ continue } - out = append(out, block) + blocks = append(blocks, model.NewBlockListEdge(block)) i++ } } + + return model.NewBlockList(blocks, hasNext), err } // LatestBlockHeight is the resolver for the latestBlockHeight field. diff --git a/serve/graph/schema/query.graphql b/serve/graph/schema/query.graphql index 5ab9c837..1c1aa3f5 100644 --- a/serve/graph/schema/query.graphql +++ b/serve/graph/schema/query.graphql @@ -4,13 +4,15 @@ Root Query type to fetch data about Blocks and Transactions based on filters or type Query { """ Retrieves a list of Transactions that match the given filter criteria. If the result is incomplete due to errors, both partial results and errors are returned. + Options of `after`, `size`, and `ascending` can be used to utilize pagination. """ - transactions(filter: TransactionFilter!): [Transaction!] + transactions(filter: TransactionFilter!, after: Cursor, size: Int, ascending: Boolean! = true): TransactionList! """ Fetches Blocks matching the specified filter criteria. Incomplete results due to errors return both the partial Blocks and the associated errors. + Options of `after`, `size`, and `ascending` can be used to utilize pagination. """ - blocks(filter: BlockFilter!): [Block!] + blocks(filter: BlockFilter!, after: Cursor, size: Int, ascending: Boolean! = true): BlockList! """ Returns the height of the most recently processed Block by the blockchain indexer, indicating the current length of the blockchain. diff --git a/serve/graph/schema/schema.graphql b/serve/graph/schema/schema.graphql index 2b8bc3ff..4a3e2625 100644 --- a/serve/graph/schema/schema.graphql +++ b/serve/graph/schema/schema.graphql @@ -7,3 +7,8 @@ schema { Field representing a point on time. It is following the RFC3339Nano format ("2006-01-02T15:04:05.999999999Z07:00") """ scalar Time + +""" +Cursor is a string representing position in a sequential list of edges. +""" +scalar Cursor diff --git a/serve/graph/schema/types/block_list.graphql b/serve/graph/schema/types/block_list.graphql new file mode 100644 index 00000000..234e8608 --- /dev/null +++ b/serve/graph/schema/types/block_list.graphql @@ -0,0 +1,23 @@ +""" +BlockList is a list of block edges provided by sequential access request. +""" +type BlockList { + """ + Edges contains provided edges of the sequential list. + """ + edges: [BlockListEdge!]! + + """ + PageInfo is an information about the current page of block edges. + """ + pageInfo: PageInfo! +} + +""" +BlockListEdge is a single edge in a sequential list of blocks. +""" +type BlockListEdge { + block: Block! + + cursor: Cursor! +} diff --git a/serve/graph/schema/types/page_info.graphql b/serve/graph/schema/types/page_info.graphql new file mode 100644 index 00000000..009ca4d3 --- /dev/null +++ b/serve/graph/schema/types/page_info.graphql @@ -0,0 +1,19 @@ +""" +PageInfo contains information about a sequential access list page. +""" +type PageInfo { + """ + `first` is the cursor of the first edge of the edges list. null for empty list. + """ + first: Cursor + + """ + `last` if the cursor of the last edge of the edges list. null for empty list. + """ + last: Cursor + + """ + `hasNext` specifies if there is another edge after the last one. + """ + hasNext: Boolean! +} diff --git a/serve/graph/schema/types/transaction_list.graphql b/serve/graph/schema/types/transaction_list.graphql new file mode 100644 index 00000000..0008a6ea --- /dev/null +++ b/serve/graph/schema/types/transaction_list.graphql @@ -0,0 +1,19 @@ +""" +TransactionList is a list of transaction edges provided by sequential access request. +""" +type TransactionList { + # Edges contains provided edges of the sequential list. + edges: [TransactionListEdge!]! + + # PageInfo is an information about the current page of transaction edges. + pageInfo: PageInfo! +} + +""" +TransactionListEdge is a single edge in a sequential list of transactions. +""" +type TransactionListEdge { + transaction: Transaction! + + cursor: Cursor! +} diff --git a/storage/pebble.go b/storage/pebble.go index 3ae7fe83..e851539b 100644 --- a/storage/pebble.go +++ b/storage/pebble.go @@ -153,11 +153,13 @@ func (s *Pebble) GetTxByHash(txHash string) (*types.TxResult, error) { return decodeTx(tx) } -func (s *Pebble) BlockIterator(fromBlockNum, toBlockNum uint64) (Iterator[*types.Block], error) { +func (s *Pebble) BlockIterator(fromBlockNum, toBlockNum uint64, ascending bool) (Iterator[*types.Block], error) { fromKey := keyBlock(fromBlockNum) if toBlockNum == 0 { toBlockNum = math.MaxInt64 + } else { + toBlockNum++ } toKey := keyBlock(toBlockNum) @@ -172,7 +174,7 @@ func (s *Pebble) BlockIterator(fromBlockNum, toBlockNum uint64) (Iterator[*types return nil, multierr.Append(snap.Close(), err) } - return &PebbleBlockIter{i: it, s: snap}, nil + return &PebbleBlockIter{i: it, s: snap, ascending: ascending}, nil } func (s *Pebble) TxIterator( @@ -180,9 +182,8 @@ func (s *Pebble) TxIterator( toBlockNum uint64, fromTxIndex, toTxIndex uint32, + ascending bool, ) (Iterator[*types.TxResult], error) { - fromKey := keyTx(fromBlockNum, fromTxIndex) - if toBlockNum == 0 { toBlockNum = math.MaxInt64 } @@ -191,6 +192,8 @@ func (s *Pebble) TxIterator( toTxIndex = math.MaxUint32 } + fromKey := keyTx(fromBlockNum, fromTxIndex) + toKey := keyTx(toBlockNum, toTxIndex) snap := s.db.NewSnapshot() @@ -203,7 +206,7 @@ func (s *Pebble) TxIterator( return nil, multierr.Append(snap.Close(), err) } - return &PebbleTxIter{i: it, s: snap, fromIndex: fromTxIndex, toIndex: toTxIndex}, nil + return &PebbleTxIter{i: it, s: snap, fromIndex: fromTxIndex, toIndex: toTxIndex, ascending: ascending}, nil } func (s *Pebble) WriteBatch() Batch { @@ -222,17 +225,18 @@ type PebbleBlockIter struct { i *pebble.Iterator s *pebble.Snapshot - init bool + init bool + ascending bool } func (pi *PebbleBlockIter) Next() bool { if !pi.init { pi.init = true - return pi.i.First() + return pi.first() } - return pi.i.Valid() && pi.i.Next() + return pi.i.Valid() && pi.next() } func (pi *PebbleBlockIter) Error() error { @@ -247,6 +251,22 @@ func (pi *PebbleBlockIter) Close() error { return multierr.Append(pi.i.Close(), pi.s.Close()) } +func (pi *PebbleBlockIter) first() bool { + if pi.ascending { + return pi.i.First() + } + + return pi.i.Last() +} + +func (pi *PebbleBlockIter) next() bool { + if pi.ascending { + return pi.i.Next() + } + + return pi.i.Prev() +} + var _ Iterator[*types.TxResult] = &PebbleTxIter{} type PebbleTxIter struct { @@ -256,17 +276,18 @@ type PebbleTxIter struct { fromIndex uint32 toIndex uint32 init bool + ascending bool } func (pi *PebbleTxIter) Next() bool { for { if !pi.init { - if !pi.i.First() { + if !pi.first() { return false } pi.init = true - } else if !pi.i.Next() { + } else if !pi.i.Valid() || !pi.next() { return false } @@ -315,6 +336,22 @@ func (pi *PebbleTxIter) Close() error { return multierr.Append(pi.i.Close(), pi.s.Close()) } +func (pi *PebbleTxIter) first() bool { + if pi.ascending { + return pi.i.First() + } + + return pi.i.Last() +} + +func (pi *PebbleTxIter) next() bool { + if pi.ascending { + return pi.i.Next() + } + + return pi.i.Prev() +} + var _ Batch = &PebbleBatch{} type PebbleBatch struct { diff --git a/storage/pebble_test.go b/storage/pebble_test.go index bc054a1a..c8c4ae7c 100644 --- a/storage/pebble_test.go +++ b/storage/pebble_test.go @@ -126,7 +126,7 @@ func TestStorageIters(t *testing.T) { require.NoError(t, wb.Commit()) - it, err := s.TxIterator(0, 0, 0, 3) + it, err := s.TxIterator(0, 0, 0, 3, true) require.NoError(t, err) txCount := 0 @@ -149,7 +149,7 @@ func TestStorageIters(t *testing.T) { defer require.NoError(t, it.Close()) - it2, err := s.BlockIterator(0, 2) + it2, err := s.BlockIterator(0, 2, true) require.NoError(t, err) blockCount := 0 @@ -167,11 +167,11 @@ func TestStorageIters(t *testing.T) { blockCount++ } - require.Equal(t, 2, blockCount) + require.Equal(t, 3, blockCount) defer require.NoError(t, it2.Close()) - it, err = s.TxIterator(0, 0, 20000, 30000) + it, err = s.TxIterator(0, 0, 20000, 30000, true) require.NoError(t, err) txCount = 0 diff --git a/storage/types.go b/storage/types.go index 3fff1241..09945cea 100644 --- a/storage/types.go +++ b/storage/types.go @@ -29,11 +29,17 @@ type Reader interface { GetTxByHash(txHash string) (*types.TxResult, error) // BlockIterator iterates over Blocks, limiting the results to be between the provided block numbers - BlockIterator(fromBlockNum, toBlockNum uint64) (Iterator[*types.Block], error) + BlockIterator(fromBlockNum, toBlockNum uint64, ascending bool) (Iterator[*types.Block], error) // TxIterator iterates over transactions, limiting the results to be between the provided block numbers // and transaction indexes - TxIterator(fromBlockNum, toBlockNum uint64, fromTxIndex, toTxIndex uint32) (Iterator[*types.TxResult], error) + TxIterator( + fromBlockNum, + toBlockNum uint64, + fromTxIndex, + toTxIndex uint32, + ascending bool, + ) (Iterator[*types.TxResult], error) } type Iterator[T any] interface {