diff --git a/gqlgen.yml b/gqlgen.yml index af53e13f..c35bc233 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -90,3 +90,6 @@ models: TransactionMessage: model: - github.com/gnolang/tx-indexer/serve/graph/model.TransactionMessage + TransactionResponse: + model: + - github.com/gnolang/tx-indexer/serve/graph/model.TransactionResponse diff --git a/serve/graph/generated.go b/serve/graph/generated.go index ee954d85..681de29d 100644 --- a/serve/graph/generated.go +++ b/serve/graph/generated.go @@ -114,6 +114,7 @@ type ComplexityRoot struct { Index func(childComplexity int) int Memo func(childComplexity int) int Messages func(childComplexity int) int + Response func(childComplexity int) int Success func(childComplexity int) int } @@ -123,6 +124,13 @@ type ComplexityRoot struct { Value func(childComplexity int) int } + TransactionResponse struct { + Data func(childComplexity int) int + Error func(childComplexity int) int + Info func(childComplexity int) int + Log func(childComplexity int) int + } + TxFee struct { GasFee func(childComplexity int) int GasWanted func(childComplexity int) int @@ -441,6 +449,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Transaction.Messages(childComplexity), true + case "Transaction.response": + if e.complexity.Transaction.Response == nil { + break + } + + return e.complexity.Transaction.Response(childComplexity), true + case "Transaction.success": if e.complexity.Transaction.Success == nil { break @@ -469,6 +484,34 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.TransactionMessage.Value(childComplexity), true + case "TransactionResponse.data": + if e.complexity.TransactionResponse.Data == nil { + break + } + + return e.complexity.TransactionResponse.Data(childComplexity), true + + case "TransactionResponse.error": + if e.complexity.TransactionResponse.Error == nil { + break + } + + return e.complexity.TransactionResponse.Error(childComplexity), true + + case "TransactionResponse.info": + if e.complexity.TransactionResponse.Info == nil { + break + } + + return e.complexity.TransactionResponse.Info(childComplexity), true + + case "TransactionResponse.log": + if e.complexity.TransactionResponse.Log == nil { + break + } + + return e.complexity.TransactionResponse.Log(childComplexity), true + case "TxFee.gas_fee": if e.complexity.TxFee.GasFee == nil { break @@ -1873,6 +1916,8 @@ func (ec *executionContext) fieldContext_Query_transactions(ctx context.Context, 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) }, @@ -2199,6 +2244,8 @@ func (ec *executionContext) fieldContext_Subscription_transactions(ctx context.C 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) }, @@ -2702,6 +2749,60 @@ func (ec *executionContext) fieldContext_Transaction_memo(ctx context.Context, f 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) + } + return nil, fmt.Errorf("no field named %q was found under type TransactionResponse", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _TransactionMessage_typeUrl(ctx context.Context, field graphql.CollectedField, obj *model.TransactionMessage) (ret graphql.Marshaler) { fc, err := ec.fieldContext_TransactionMessage_typeUrl(ctx, field) if err != nil { @@ -2834,6 +2935,182 @@ func (ec *executionContext) fieldContext_TransactionMessage_value(ctx context.Co return fc, nil } +func (ec *executionContext) _TransactionResponse_log(ctx context.Context, field graphql.CollectedField, obj *model.TransactionResponse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionResponse_log(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.Log(), 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_TransactionResponse_log(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TransactionResponse", + 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) _TransactionResponse_info(ctx context.Context, field graphql.CollectedField, obj *model.TransactionResponse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionResponse_info(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.Info(), 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_TransactionResponse_info(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TransactionResponse", + 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) _TransactionResponse_error(ctx context.Context, field graphql.CollectedField, obj *model.TransactionResponse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionResponse_error(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.Error(), 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_TransactionResponse_error(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TransactionResponse", + 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) _TransactionResponse_data(ctx context.Context, field graphql.CollectedField, obj *model.TransactionResponse) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TransactionResponse_data(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.Data(), 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_TransactionResponse_data(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TransactionResponse", + 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) _TxFee_gas_wanted(ctx context.Context, field graphql.CollectedField, obj *model.TxFee) (ret graphql.Marshaler) { fc, err := ec.fieldContext_TxFee_gas_wanted(ctx, field) if err != nil { @@ -5893,6 +6170,11 @@ 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) + if out.Values[i] == graphql.Null { + out.Invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -5965,6 +6247,60 @@ func (ec *executionContext) _TransactionMessage(ctx context.Context, sel ast.Sel return out } +var transactionResponseImplementors = []string{"TransactionResponse"} + +func (ec *executionContext) _TransactionResponse(ctx context.Context, sel ast.SelectionSet, obj *model.TransactionResponse) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, transactionResponseImplementors) + + 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("TransactionResponse") + case "log": + out.Values[i] = ec._TransactionResponse_log(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "info": + out.Values[i] = ec._TransactionResponse_info(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "error": + out.Values[i] = ec._TransactionResponse_error(ctx, field, obj) + if out.Values[i] == graphql.Null { + out.Invalids++ + } + case "data": + out.Values[i] = ec._TransactionResponse_data(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 txFeeImplementors = []string{"TxFee"} func (ec *executionContext) _TxFee(ctx context.Context, sel ast.SelectionSet, obj *model.TxFee) graphql.Marshaler { @@ -6555,6 +6891,16 @@ func (ec *executionContext) marshalNTransactionMessage2ᚕᚖgithub.comᚋgnol return ret } +func (ec *executionContext) marshalNTransactionResponse2ᚖgithub.comᚋgnolangᚋtxᚑindexerᚋserveᚋgraphᚋmodelᚐTransactionResponse(ctx context.Context, sel ast.SelectionSet, v *model.TransactionResponse) 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._TransactionResponse(ctx, sel, v) +} + func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { return ec.___Directive(ctx, sel, &v) } diff --git a/serve/graph/model/transaction.go b/serve/graph/model/transaction.go index 9d8b733c..55f03c93 100644 --- a/serve/graph/model/transaction.go +++ b/serve/graph/model/transaction.go @@ -8,6 +8,7 @@ import ( "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/tm2/pkg/amino" + abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/sdk/bank" "github.com/gnolang/gno/tm2/pkg/std" @@ -27,7 +28,6 @@ func NewTransaction(txResult *types.TxResult) *Transaction { return &Transaction{ txResult: txResult, messages: make([]*TransactionMessage, 0), - stdTx: nil, } } @@ -51,6 +51,10 @@ func (t *Transaction) Success() bool { return t.txResult.Response.IsOK() } +func (t *Transaction) Response() *TransactionResponse { + return &TransactionResponse{response: t.txResult.Response} +} + func (t *Transaction) GasWanted() int { return int(t.txResult.Response.GasWanted) } @@ -120,6 +124,31 @@ func (t *Transaction) getMessages() []*TransactionMessage { return t.messages } +//nolint:errname // Provide a field named `error` as the GraphQL response value +type TransactionResponse struct { + response abci.ResponseDeliverTx +} + +func (tr *TransactionResponse) Log() string { + return tr.response.Log +} + +func (tr *TransactionResponse) Info() string { + return tr.response.Info +} + +func (tr *TransactionResponse) Error() string { + if tr.response.IsErr() { + return tr.response.Error.Error() + } + + return "" +} + +func (tr *TransactionResponse) Data() string { + return string(tr.response.Data) +} + type TransactionMessage struct { Value MessageValue Route string diff --git a/serve/graph/schema/types/transaction.graphql b/serve/graph/schema/types/transaction.graphql index d1d2b0ea..0d834693 100644 --- a/serve/graph/schema/types/transaction.graphql +++ b/serve/graph/schema/types/transaction.graphql @@ -49,6 +49,12 @@ type Transaction { For example, when trading a specific exchange, you would utilize the memo field of the transaction. """ memo: String! + + """ + `response` is the processing result of the transaction. + It has `log`, `info`, `error`, and `data`. + """ + response: TransactionResponse! } """ @@ -268,3 +274,29 @@ type TxFee { """ gas_fee: Int! } + +""" +`TransactionResponse` is the processing result of the transaction. +It has `log`, `info`, `error`, and `data`. +""" +type TransactionResponse { + """ + The log value associated with the Transaction execution, if any. + """ + log: String! + + """ + The Info associated with the Transaction execution, if any. + """ + info: String! + + """ + The error value associated with the Transaction execution, if any. + """ + error: String! + + """ + The response data associated with the Transaction execution, if any. + """ + data: String! +}