[wip] gql server fixes
run gql server gql cleanup
This commit is contained in:
parent
c48710ab82
commit
f0f96bc28e
@ -34,6 +34,7 @@ import (
|
||||
genutilv2cli "github.com/cosmos/cosmos-sdk/x/genutil/v2/cli"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/app"
|
||||
"git.vdb.to/cerc-io/laconicd/gql"
|
||||
"git.vdb.to/cerc-io/laconicd/nitro"
|
||||
// "git.vdb.to/cerc-io/laconicd/x/nitrobank"
|
||||
)
|
||||
@ -90,6 +91,7 @@ func InitRootCmd[T app.Tx](
|
||||
&telemetry.Server[T]{},
|
||||
&rest.Server[T]{},
|
||||
&nitro.Server{},
|
||||
&gql.Server{},
|
||||
)
|
||||
}
|
||||
|
||||
@ -152,6 +154,11 @@ func InitRootCmd[T app.Tx](
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlServer, err := gql.New(logger, deps.GlobalConfig, deps.ClientContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// wire server commands
|
||||
return serverv2.AddCommands[T](
|
||||
rootCmd,
|
||||
@ -165,6 +172,7 @@ func InitRootCmd[T app.Tx](
|
||||
telemetryServer,
|
||||
restServer,
|
||||
nitroServer,
|
||||
gqlServer,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ On having some change in the GQL schema (for example: adding a new query) update
|
||||
## Start server
|
||||
|
||||
```shell
|
||||
laconicd start --gql-playground --gql-server
|
||||
laconicd start --gql.playground --gql.server
|
||||
```
|
||||
|
||||
Basic node status:
|
||||
|
19
gql/config.go
Normal file
19
gql/config.go
Normal file
@ -0,0 +1,19 @@
|
||||
package gql
|
||||
|
||||
func DefaultConfig() *Config {
|
||||
return &Config{
|
||||
Enable: false,
|
||||
Playground: false,
|
||||
PlaygroundAPIBase: "",
|
||||
Port: 9473,
|
||||
// LogFile: "",
|
||||
}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Enable bool `mapstructure:"enable" toml:"enable" comment:"Enable the GraphQL server."`
|
||||
Playground bool `mapstructure:"playground" toml:"playground" comment:"Enable the GraphQL playground."`
|
||||
PlaygroundAPIBase string `mapstructure:"playground-api-base" toml:"playground-api-base" comment:"GraphQL API base path to use in the playground."`
|
||||
Port uint `mapstructure:"port" toml:"port" comment:"Port to use for the GraphQL server."`
|
||||
// LogFile string `mapstructure:"log-file" toml:"log-file" comment:"File to tail for the 'getLogs' API."`
|
||||
}
|
29
gql/flags.go
29
gql/flags.go
@ -1,15 +1,24 @@
|
||||
package gql
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
import "github.com/spf13/pflag"
|
||||
|
||||
// AddGQLFlags adds gql flags for
|
||||
func AddGQLFlags(cmd *cobra.Command) *cobra.Command {
|
||||
// Add flags for GQL server.
|
||||
cmd.PersistentFlags().Bool("gql-server", false, "Start GQL server.")
|
||||
cmd.PersistentFlags().Bool("gql-playground", false, "Enable GQL playground.")
|
||||
cmd.PersistentFlags().String("gql-playground-api-base", "", "GQL API base path to use in GQL playground.")
|
||||
cmd.PersistentFlags().String("gql-port", "9473", "Port to use for the GQL server.")
|
||||
cmd.PersistentFlags().String("log-file", "", "File to tail for GQL 'getLogs' API.")
|
||||
var (
|
||||
FlagEnable = prefix("enable")
|
||||
FlagPlayground = prefix("playground")
|
||||
FlagPlaygroundAPIBase = prefix("playground-api-base")
|
||||
FlagPort = prefix("port")
|
||||
//FlagLogFile = prefix("log-file")
|
||||
)
|
||||
|
||||
return cmd
|
||||
// AddGQLFlags adds flags for the GraphQL server.
|
||||
func AddGQLFlags(flags *pflag.FlagSet) {
|
||||
flags.Bool(FlagEnable, false, "Enable the GraphQL server")
|
||||
flags.Bool(FlagPlayground, false, "Enable the GraphQL playground")
|
||||
flags.String(FlagPlaygroundAPIBase, "", "GraphQL API base path to use in the playground")
|
||||
flags.String(FlagPort, "9473", "Port to use for the GraphQL server.")
|
||||
// cmd.PersistentFlags().String(FlagLogFile, "", "File to tail for GraphQL 'getLogs' API")
|
||||
}
|
||||
|
||||
func prefix(f string) string {
|
||||
return ServerName + "." + f
|
||||
}
|
||||
|
@ -4,9 +4,9 @@
|
||||
schema:
|
||||
- cerc-io/laconicd/*.graphql
|
||||
exec:
|
||||
filename: generated.go
|
||||
filename: schema/generated.go
|
||||
model:
|
||||
filename: models_gen.go
|
||||
filename: schema/models_gen.go
|
||||
resolver:
|
||||
filename: resolver.go
|
||||
type: Resolver
|
||||
@ -14,4 +14,4 @@ resolver:
|
||||
models:
|
||||
Link:
|
||||
model:
|
||||
- git.vdb.to/cerc-io/laconicd/gql.Link
|
||||
- git.vdb.to/cerc-io/laconicd/gql/schema.Link
|
||||
|
@ -6,12 +6,13 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/query"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "cosmossdk.io/x/bank/types"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
onboardingTypes "git.vdb.to/cerc-io/laconicd/x/onboarding"
|
||||
@ -33,13 +34,13 @@ type Resolver struct {
|
||||
}
|
||||
|
||||
// Query is the entry point to query execution.
|
||||
func (r *Resolver) Query() QueryResolver {
|
||||
func (r *Resolver) Query() schema.QueryResolver {
|
||||
return &queryResolver{r}
|
||||
}
|
||||
|
||||
type queryResolver struct{ *Resolver }
|
||||
|
||||
func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*Authority, error) {
|
||||
func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*schema.Authority, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
|
||||
@ -53,14 +54,14 @@ func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*Au
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authorities := make([]*Authority, len(authoritiesResp.GetAuthorities()))
|
||||
authorities := make([]*schema.Authority, len(authoritiesResp.GetAuthorities()))
|
||||
for i, a := range authoritiesResp.Authorities {
|
||||
entry, err := getAuthorityRecord(*a.Entry, auctionQueryClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authorities[i] = &Authority{
|
||||
authorities[i] = &schema.Authority{
|
||||
Name: a.Name,
|
||||
Entry: entry,
|
||||
}
|
||||
@ -69,10 +70,10 @@ func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*Au
|
||||
return authorities, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*AuthorityRecord, error) {
|
||||
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*schema.AuthorityRecord, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
gqlResponse := []*AuthorityRecord{}
|
||||
gqlResponse := []*schema.AuthorityRecord{}
|
||||
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.Whois(context.Background(), ®istrytypes.QueryWhoisRequest{Name: name})
|
||||
@ -97,9 +98,9 @@ func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*Record, error) {
|
||||
func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*schema.Record, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*Record
|
||||
var gqlResponse []*schema.Record
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.ResolveLrn(context.Background(), ®istrytypes.QueryResolveLrnRequest{Lrn: name})
|
||||
if err != nil {
|
||||
@ -118,9 +119,9 @@ func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*Rec
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*NameRecord, error) {
|
||||
func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*schema.NameRecord, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*NameRecord
|
||||
var gqlResponse []*schema.NameRecord
|
||||
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.LookupLrn(context.Background(), ®istrytypes.QueryLookupLrnRequest{Lrn: name})
|
||||
@ -140,7 +141,7 @@ func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*Name
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueInput, all *bool, limit *int, offset *int) ([]*Record, error) {
|
||||
func (q queryResolver) QueryRecords(ctx context.Context, attributes []*schema.KeyValueInput, all *bool, limit *int, offset *int) ([]*schema.Record, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
|
||||
var pagination *query.PageRequest
|
||||
@ -175,7 +176,7 @@ func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueI
|
||||
}
|
||||
|
||||
records := res.GetRecords()
|
||||
gqlResponse := make([]*Record, len(records))
|
||||
gqlResponse := make([]*schema.Record, len(records))
|
||||
|
||||
for i, record := range records {
|
||||
gqlRecord, err := getGQLRecord(context.Background(), q, record)
|
||||
@ -188,9 +189,9 @@ func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueI
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Record, error) {
|
||||
func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*schema.Record, error) {
|
||||
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
||||
gqlResponse := make([]*Record, len(ids))
|
||||
gqlResponse := make([]*schema.Record, len(ids))
|
||||
|
||||
for i, id := range ids {
|
||||
res, err := nsQueryClient.GetRecord(context.Background(), ®istrytypes.QueryGetRecordRequest{Id: id})
|
||||
@ -209,7 +210,7 @@ func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Re
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||
func (q queryResolver) GetStatus(ctx context.Context) (*schema.Status, error) {
|
||||
nodeInfo, syncInfo, validatorInfo, err := getStatusInfo(q.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -230,7 +231,7 @@ func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Status{
|
||||
return &schema.Status{
|
||||
Version: RegistryVersion,
|
||||
Node: nodeInfo,
|
||||
Sync: syncInfo,
|
||||
@ -242,8 +243,8 @@ func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*Account, error) {
|
||||
accounts := make([]*Account, len(addresses))
|
||||
func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*schema.Account, error) {
|
||||
accounts := make([]*schema.Account, len(addresses))
|
||||
for index, address := range addresses {
|
||||
account, err := q.GetAccount(ctx, address)
|
||||
if err != nil {
|
||||
@ -254,7 +255,7 @@ func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account, error) {
|
||||
func (q queryResolver) GetAccount(ctx context.Context, address string) (*schema.Account, error) {
|
||||
authQueryClient := authtypes.NewQueryClient(q.ctx)
|
||||
accountResponse, err := authQueryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: address})
|
||||
if err != nil {
|
||||
@ -280,7 +281,7 @@ func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account
|
||||
accNum := strconv.FormatUint(account.GetAccountNumber(), 10)
|
||||
seq := strconv.FormatUint(account.GetSequence(), 10)
|
||||
|
||||
return &Account{
|
||||
return &schema.Account{
|
||||
Address: address,
|
||||
Number: accNum,
|
||||
Sequence: seq,
|
||||
@ -289,8 +290,8 @@ func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*Bond, error) {
|
||||
bonds := make([]*Bond, len(ids))
|
||||
func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*schema.Bond, error) {
|
||||
bonds := make([]*schema.Bond, len(ids))
|
||||
for index, id := range ids {
|
||||
bondObj, err := q.GetBond(ctx, id)
|
||||
if err != nil {
|
||||
@ -302,7 +303,7 @@ func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*Bond
|
||||
return bonds, nil
|
||||
}
|
||||
|
||||
func (q *queryResolver) GetBond(ctx context.Context, id string) (*Bond, error) {
|
||||
func (q *queryResolver) GetBond(ctx context.Context, id string) (*schema.Bond, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bondResp, err := bondQueryClient.GetBondById(context.Background(), &bondtypes.QueryGetBondByIdRequest{Id: id})
|
||||
if err != nil {
|
||||
@ -320,14 +321,14 @@ func (q *queryResolver) GetBond(ctx context.Context, id string) (*Bond, error) {
|
||||
return getGQLBond(bondResp.GetBond())
|
||||
}
|
||||
|
||||
func (q queryResolver) QueryBonds(ctx context.Context) ([]*Bond, error) {
|
||||
func (q queryResolver) QueryBonds(ctx context.Context) ([]*schema.Bond, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bonds, err := bondQueryClient.Bonds(context.Background(), &bondtypes.QueryBondsRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlResponse := make([]*Bond, len(bonds.GetBonds()))
|
||||
gqlResponse := make([]*schema.Bond, len(bonds.GetBonds()))
|
||||
for i, bondObj := range bonds.GetBonds() {
|
||||
gqlBond, err := getGQLBond(bondObj)
|
||||
if err != nil {
|
||||
@ -340,8 +341,8 @@ func (q queryResolver) QueryBonds(ctx context.Context) ([]*Bond, error) {
|
||||
}
|
||||
|
||||
// QueryBondsByOwner will return bonds by owner
|
||||
func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []string) ([]*OwnerBonds, error) {
|
||||
ownerBonds := make([]*OwnerBonds, len(ownerAddresses))
|
||||
func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []string) ([]*schema.OwnerBonds, error) {
|
||||
ownerBonds := make([]*schema.OwnerBonds, len(ownerAddresses))
|
||||
for index, ownerAddress := range ownerAddresses {
|
||||
bondsObj, err := q.GetBondsByOwner(ctx, ownerAddress)
|
||||
if err != nil {
|
||||
@ -353,14 +354,14 @@ func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []s
|
||||
return ownerBonds, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*OwnerBonds, error) {
|
||||
func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*schema.OwnerBonds, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bondResp, err := bondQueryClient.GetBondsByOwner(context.Background(), &bondtypes.QueryGetBondsByOwnerRequest{Owner: address})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ownerBonds := make([]*Bond, len(bondResp.GetBonds()))
|
||||
ownerBonds := make([]*schema.Bond, len(bondResp.GetBonds()))
|
||||
for i, bond := range bondResp.GetBonds() {
|
||||
// #nosec G601
|
||||
bondObj, err := getGQLBond(&bond) //nolint: all
|
||||
@ -370,12 +371,12 @@ func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*Ow
|
||||
ownerBonds[i] = bondObj
|
||||
}
|
||||
|
||||
return &OwnerBonds{Bonds: ownerBonds, Owner: address}, nil
|
||||
return &schema.OwnerBonds{Bonds: ownerBonds, Owner: address}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*Auction, error) {
|
||||
func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*schema.Auction, error) {
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
gqlAuctionResponse := make([]*Auction, len(ids))
|
||||
gqlAuctionResponse := make([]*schema.Auction, len(ids))
|
||||
for i, id := range ids {
|
||||
auctionObj, err := auctionQueryClient.GetAuction(context.Background(), &auctiontypes.QueryGetAuctionRequest{Id: id})
|
||||
if err != nil {
|
||||
@ -397,16 +398,16 @@ func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*A
|
||||
return gqlAuctionResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetParticipants(ctx context.Context) ([]*Participant, error) {
|
||||
func (q queryResolver) GetParticipants(ctx context.Context) ([]*schema.Participant, error) {
|
||||
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
||||
participantResp, err := onboardingQueryClient.Participants(context.Background(), &onboardingTypes.QueryParticipantsRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
participants := make([]*Participant, len(participantResp.GetParticipants()))
|
||||
participants := make([]*schema.Participant, len(participantResp.GetParticipants()))
|
||||
for i, p := range participantResp.Participants {
|
||||
participants[i] = &Participant{
|
||||
participants[i] = &schema.Participant{
|
||||
CosmosAddress: p.CosmosAddress,
|
||||
NitroAddress: p.NitroAddress,
|
||||
Role: p.Role,
|
||||
@ -417,7 +418,7 @@ func (q queryResolver) GetParticipants(ctx context.Context) ([]*Participant, err
|
||||
return participants, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetParticipantByAddress(ctx context.Context, address string) (*Participant, error) {
|
||||
func (q queryResolver) GetParticipantByAddress(ctx context.Context, address string) (*schema.Participant, error) {
|
||||
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
||||
participantResp, err := onboardingQueryClient.GetParticipantByAddress(ctx, &onboardingTypes.QueryGetParticipantByAddressRequest{Address: address})
|
||||
if err != nil {
|
||||
@ -425,7 +426,7 @@ func (q queryResolver) GetParticipantByAddress(ctx context.Context, address stri
|
||||
}
|
||||
|
||||
p := participantResp.Participant
|
||||
participant := &Participant{
|
||||
participant := &schema.Participant{
|
||||
CosmosAddress: p.CosmosAddress,
|
||||
NitroAddress: p.NitroAddress,
|
||||
Role: p.Role,
|
||||
@ -435,7 +436,7 @@ func (q queryResolver) GetParticipantByAddress(ctx context.Context, address stri
|
||||
return participant, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAddress string) (*Participant, error) {
|
||||
func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAddress string) (*schema.Participant, error) {
|
||||
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
||||
participantResp, err := onboardingQueryClient.GetParticipantByNitroAddress(
|
||||
ctx,
|
||||
@ -448,7 +449,7 @@ func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAd
|
||||
}
|
||||
|
||||
p := participantResp.Participant
|
||||
participant := &Participant{
|
||||
participant := &schema.Participant{
|
||||
CosmosAddress: p.CosmosAddress,
|
||||
NitroAddress: p.NitroAddress,
|
||||
Role: p.Role,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
package gql
|
||||
package schema
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,6 +1,6 @@
|
||||
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||
|
||||
package gql
|
||||
package schema
|
||||
|
||||
type Value interface {
|
||||
IsValue()
|
128
gql/server.go
128
gql/server.go
@ -2,74 +2,124 @@ package gql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/core/server"
|
||||
"cosmossdk.io/core/transaction"
|
||||
"cosmossdk.io/log"
|
||||
serverv2 "cosmossdk.io/server/v2"
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/cors"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// Server configures and starts the GQL server.
|
||||
func Server(ctx context.Context, clientCtx client.Context, logger log.Logger) error {
|
||||
if !viper.GetBool("gql-server") {
|
||||
return nil
|
||||
const (
|
||||
ServerName = "gql"
|
||||
)
|
||||
|
||||
var (
|
||||
_ serverv2.ServerComponent[transaction.Tx] = (*Server)(nil)
|
||||
_ serverv2.HasStartFlags = (*Server)(nil)
|
||||
_ serverv2.HasConfig = (*Server)(nil)
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
logger log.Logger
|
||||
router chi.Router
|
||||
config *Config
|
||||
httpServer *http.Server
|
||||
}
|
||||
|
||||
func New(logger log.Logger, cfg server.ConfigMap, clientCtx client.Context) (*Server, error) {
|
||||
s := &Server{
|
||||
logger: logger.With(log.ModuleKey, ServerName),
|
||||
router: chi.NewRouter(),
|
||||
}
|
||||
|
||||
router := chi.NewRouter()
|
||||
s.config = s.Config().(*Config)
|
||||
if len(cfg) > 0 {
|
||||
if err := serverv2.UnmarshalSubConfig(cfg, s.Name(), &s.config); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Add CORS middleware around every request
|
||||
// See https://github.com/rs/cors for full option listing
|
||||
router.Use(cors.New(cors.Options{
|
||||
s.router.Use(cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
Debug: false,
|
||||
}).Handler)
|
||||
|
||||
logFile := viper.GetString("log-file")
|
||||
|
||||
port := viper.GetString("gql-port")
|
||||
|
||||
srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: &Resolver{
|
||||
ctx: clientCtx,
|
||||
logFile: logFile,
|
||||
srv := handler.NewDefaultServer(schema.NewExecutableSchema(schema.Config{Resolvers: &Resolver{
|
||||
ctx: clientCtx,
|
||||
// logFile: logFile,
|
||||
}}))
|
||||
|
||||
router.Handle("/", PlaygroundHandler("/api"))
|
||||
s.router.Handle("/", PlaygroundHandler("/api"))
|
||||
|
||||
if viper.GetBool("gql-playground") {
|
||||
apiBase := viper.GetString("gql-playground-api-base")
|
||||
|
||||
router.Handle("/webui", PlaygroundHandler(apiBase+"/api"))
|
||||
router.Handle("/console", PlaygroundHandler(apiBase+"/graphql"))
|
||||
if s.config.Playground {
|
||||
apiBase := s.config.PlaygroundAPIBase
|
||||
s.router.Handle("/webui", PlaygroundHandler(apiBase+"/api"))
|
||||
s.router.Handle("/console", PlaygroundHandler(apiBase+"/graphql"))
|
||||
}
|
||||
|
||||
router.Handle("/api", srv)
|
||||
router.Handle("/graphql", srv)
|
||||
s.router.Handle("/api", srv)
|
||||
s.router.Handle("/graphql", srv)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
errCh := make(chan error)
|
||||
func (s *Server) Name() string {
|
||||
return ServerName
|
||||
}
|
||||
|
||||
go func() {
|
||||
logger.Info(fmt.Sprintf("Connect to GraphQL playground url: http://localhost:%s", port))
|
||||
server := &http.Server{
|
||||
Addr: ":" + port,
|
||||
Handler: router,
|
||||
ReadHeaderTimeout: 3 * time.Second,
|
||||
}
|
||||
errCh <- server.ListenAndServe()
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Gracefully stop the GQL server.
|
||||
logger.Info("Stopping GQL server...")
|
||||
// Server configures and starts the GQL server.
|
||||
func (s *Server) Start(ctx context.Context) error {
|
||||
if !s.config.Enable {
|
||||
s.logger.Info(fmt.Sprintf("%s server is disabled via config", s.Name()))
|
||||
return nil
|
||||
case err := <-errCh:
|
||||
logger.Error(fmt.Sprintf("Failed to start GQL server: %s", err))
|
||||
}
|
||||
|
||||
if s.config.Playground {
|
||||
s.logger.Info(fmt.Sprintf("Connect to GraphQL playground URL at http://localhost:%d", s.config.Port))
|
||||
}
|
||||
s.httpServer = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", s.config.Port),
|
||||
Handler: s.router,
|
||||
ReadHeaderTimeout: 3 * time.Second,
|
||||
}
|
||||
if err := s.httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
s.logger.Error("Failed to start GraphQL server", "error", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) Stop(ctx context.Context) error {
|
||||
if !s.config.Enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
s.logger.Info("stopping GraphQL server")
|
||||
return s.httpServer.Shutdown(ctx)
|
||||
|
||||
}
|
||||
|
||||
func (s *Server) Config() any {
|
||||
if s.config == nil {
|
||||
return DefaultConfig()
|
||||
}
|
||||
return s.config
|
||||
}
|
||||
|
||||
func (s *Server) StartCmdFlags() *pflag.FlagSet {
|
||||
flags := pflag.NewFlagSet(s.Name(), pflag.ExitOnError)
|
||||
AddGQLFlags(flags)
|
||||
return flags
|
||||
}
|
||||
|
@ -7,13 +7,14 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// NodeDataPath is the path to the laconicd data folder.
|
||||
var NodeDataPath = os.ExpandEnv("$HOME/.laconicd/data")
|
||||
|
||||
func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo, error) {
|
||||
func getStatusInfo(client client.Context) (*schema.NodeInfo, *schema.SyncInfo, *schema.ValidatorInfo, error) {
|
||||
nodeClient, err := client.GetNode()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
@ -23,16 +24,16 @@ func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo,
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return &NodeInfo{
|
||||
return &schema.NodeInfo{
|
||||
ID: string(nodeStatus.NodeInfo.ID()),
|
||||
Network: nodeStatus.NodeInfo.Network,
|
||||
Moniker: nodeStatus.NodeInfo.Moniker,
|
||||
}, &SyncInfo{
|
||||
}, &schema.SyncInfo{
|
||||
LatestBlockHash: nodeStatus.SyncInfo.LatestBlockHash.String(),
|
||||
LatestBlockHeight: strconv.FormatInt(nodeStatus.SyncInfo.LatestBlockHeight, 10),
|
||||
LatestBlockTime: nodeStatus.SyncInfo.LatestBlockTime.String(),
|
||||
CatchingUp: nodeStatus.SyncInfo.CatchingUp,
|
||||
}, &ValidatorInfo{
|
||||
}, &schema.ValidatorInfo{
|
||||
Address: nodeStatus.ValidatorInfo.Address.String(),
|
||||
VotingPower: strconv.FormatInt(nodeStatus.ValidatorInfo.VotingPower, 10),
|
||||
ProposerPriority: nil,
|
||||
@ -40,7 +41,7 @@ func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo,
|
||||
}
|
||||
|
||||
// nolint: all
|
||||
func getNetInfo(_ client.Context) (string, []*PeerInfo, error) {
|
||||
func getNetInfo(_ client.Context) (string, []*schema.PeerInfo, error) {
|
||||
// TODO: Implement
|
||||
|
||||
// nodeClient, err := client.GetNode()
|
||||
@ -68,10 +69,10 @@ func getNetInfo(_ client.Context) (string, []*PeerInfo, error) {
|
||||
|
||||
// return strconv.FormatInt(int64(netInfo.NPeers), 10), peersInfo, nil
|
||||
|
||||
return strconv.FormatInt(int64(0), 10), []*PeerInfo{}, nil
|
||||
return strconv.FormatInt(int64(0), 10), []*schema.PeerInfo{}, nil
|
||||
}
|
||||
|
||||
func getValidatorSet(client client.Context) ([]*ValidatorInfo, error) {
|
||||
func getValidatorSet(client client.Context) ([]*schema.ValidatorInfo, error) {
|
||||
nodeClient, err := client.GetNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -81,10 +82,10 @@ func getValidatorSet(client client.Context) ([]*ValidatorInfo, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
validatorSet := make([]*ValidatorInfo, len(res.Validators))
|
||||
validatorSet := make([]*schema.ValidatorInfo, len(res.Validators))
|
||||
for index, validator := range res.Validators {
|
||||
proposerPriority := strconv.FormatInt(validator.ProposerPriority, 10)
|
||||
validatorSet[index] = &ValidatorInfo{
|
||||
validatorSet[index] = &schema.ValidatorInfo{
|
||||
Address: validator.Address.String(),
|
||||
VotingPower: strconv.FormatInt(validator.VotingPower, 10),
|
||||
ProposerPriority: &proposerPriority,
|
||||
|
73
gql/util.go
73
gql/util.go
@ -9,6 +9,7 @@ import (
|
||||
"github.com/ipld/go-ipld-prime"
|
||||
"github.com/ipld/go-ipld-prime/codec/dagjson"
|
||||
|
||||
"git.vdb.to/cerc-io/laconicd/gql/schema"
|
||||
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
||||
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
||||
registrytypes "git.vdb.to/cerc-io/laconicd/x/registry"
|
||||
@ -23,8 +24,8 @@ const BondIDAttributeName = "bondId"
|
||||
// ExpiryTimeAttributeName denotes the record expiry time.
|
||||
const ExpiryTimeAttributeName = "expiryTime"
|
||||
|
||||
func getGQLCoin(coin sdk.Coin) *Coin {
|
||||
gqlCoin := Coin{
|
||||
func getGQLCoin(coin sdk.Coin) *schema.Coin {
|
||||
gqlCoin := schema.Coin{
|
||||
Type: coin.Denom,
|
||||
Quantity: coin.Amount.BigInt().String(),
|
||||
}
|
||||
@ -32,8 +33,8 @@ func getGQLCoin(coin sdk.Coin) *Coin {
|
||||
return &gqlCoin
|
||||
}
|
||||
|
||||
func getGQLCoins(coins sdk.Coins) []*Coin {
|
||||
gqlCoins := make([]*Coin, len(coins))
|
||||
func getGQLCoins(coins sdk.Coins) []*schema.Coin {
|
||||
gqlCoins := make([]*schema.Coin, len(coins))
|
||||
for index, coin := range coins {
|
||||
gqlCoins[index] = getGQLCoin(coin)
|
||||
}
|
||||
@ -41,12 +42,12 @@ func getGQLCoins(coins sdk.Coins) []*Coin {
|
||||
return gqlCoins
|
||||
}
|
||||
|
||||
func GetGQLNameAuthorityRecord(record *registrytypes.NameAuthority) (*AuthorityRecord, error) {
|
||||
func GetGQLNameAuthorityRecord(record *registrytypes.NameAuthority) (*schema.AuthorityRecord, error) {
|
||||
if record == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &AuthorityRecord{
|
||||
return &schema.AuthorityRecord{
|
||||
OwnerAddress: record.OwnerAddress,
|
||||
OwnerPublicKey: record.OwnerPublicKey,
|
||||
Height: strconv.FormatUint(record.Height, 10),
|
||||
@ -56,7 +57,7 @@ func GetGQLNameAuthorityRecord(record *registrytypes.NameAuthority) (*AuthorityR
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getGQLRecord(ctx context.Context, resolver QueryResolver, record registrytypes.Record) (*Record, error) {
|
||||
func getGQLRecord(ctx context.Context, resolver schema.QueryResolver, record registrytypes.Record) (*schema.Record, error) {
|
||||
// Nil record.
|
||||
if record.Deleted {
|
||||
return nil, nil
|
||||
@ -81,22 +82,22 @@ func getGQLRecord(ctx context.Context, resolver QueryResolver, record registryty
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Record{
|
||||
return &schema.Record{
|
||||
ID: record.Id,
|
||||
BondID: record.GetBondId(),
|
||||
CreateTime: record.GetCreateTime(),
|
||||
ExpiryTime: record.GetExpiryTime(),
|
||||
Owners: record.GetOwners(),
|
||||
Names: record.GetNames(),
|
||||
Attributes: attributes.(MapValue).Value,
|
||||
Attributes: attributes.(schema.MapValue).Value,
|
||||
References: references,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
func resolveIPLDNode(node ipld.Node, links *[]string) (schema.Value, error) {
|
||||
switch node.Kind() {
|
||||
case ipld.Kind_Map:
|
||||
var entries []*Attribute
|
||||
var entries []*schema.Attribute
|
||||
for itr := node.MapIterator(); !itr.Done(); {
|
||||
k, v, err := itr.Next()
|
||||
if err != nil {
|
||||
@ -113,14 +114,14 @@ func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entries = append(entries, &Attribute{
|
||||
entries = append(entries, &schema.Attribute{
|
||||
Key: s,
|
||||
Value: val,
|
||||
})
|
||||
}
|
||||
return MapValue{entries}, nil
|
||||
return schema.MapValue{entries}, nil
|
||||
case ipld.Kind_List:
|
||||
var values []Value
|
||||
var values []schema.Value
|
||||
for itr := node.ListIterator(); !itr.Done(); {
|
||||
_, v, err := itr.Next()
|
||||
if err != nil {
|
||||
@ -132,7 +133,7 @@ func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
}
|
||||
values = append(values, val)
|
||||
}
|
||||
return ArrayValue{values}, nil
|
||||
return schema.ArrayValue{values}, nil
|
||||
case ipld.Kind_Null:
|
||||
return nil, nil
|
||||
case ipld.Kind_Bool:
|
||||
@ -140,82 +141,82 @@ func resolveIPLDNode(node ipld.Node, links *[]string) (Value, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return BooleanValue{val}, nil
|
||||
return schema.BooleanValue{val}, nil
|
||||
case ipld.Kind_Int:
|
||||
val, err := node.AsInt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: handle bigger ints
|
||||
return IntValue{int(val)}, nil
|
||||
return schema.IntValue{int(val)}, nil
|
||||
case ipld.Kind_Float:
|
||||
val, err := node.AsFloat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return FloatValue{val}, nil
|
||||
return schema.FloatValue{val}, nil
|
||||
case ipld.Kind_String:
|
||||
val, err := node.AsString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return StringValue{val}, nil
|
||||
return schema.StringValue{val}, nil
|
||||
case ipld.Kind_Bytes:
|
||||
val, err := node.AsBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return BytesValue{string(val)}, nil
|
||||
return schema.BytesValue{string(val)}, nil
|
||||
case ipld.Kind_Link:
|
||||
val, err := node.AsLink()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
*links = append(*links, val.String())
|
||||
return LinkValue{Link(val.String())}, nil
|
||||
return schema.LinkValue{schema.Link(val.String())}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid node kind")
|
||||
}
|
||||
}
|
||||
|
||||
func getGQLNameRecord(record *registrytypes.NameRecord) (*NameRecord, error) {
|
||||
func getGQLNameRecord(record *registrytypes.NameRecord) (*schema.NameRecord, error) {
|
||||
if record == nil {
|
||||
return nil, fmt.Errorf("got nil record")
|
||||
}
|
||||
|
||||
records := make([]*NameRecordEntry, len(record.History))
|
||||
records := make([]*schema.NameRecordEntry, len(record.History))
|
||||
for index, entry := range record.History {
|
||||
records[index] = getNameRecordEntry(entry)
|
||||
}
|
||||
|
||||
return &NameRecord{
|
||||
return &schema.NameRecord{
|
||||
Latest: getNameRecordEntry(record.Latest),
|
||||
History: records,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getNameRecordEntry(record *registrytypes.NameRecordEntry) *NameRecordEntry {
|
||||
return &NameRecordEntry{
|
||||
func getNameRecordEntry(record *registrytypes.NameRecordEntry) *schema.NameRecordEntry {
|
||||
return &schema.NameRecordEntry{
|
||||
ID: record.Id,
|
||||
Height: strconv.FormatUint(record.Height, 10),
|
||||
}
|
||||
}
|
||||
|
||||
func getGQLBond(bondObj *bondtypes.Bond) (*Bond, error) {
|
||||
func getGQLBond(bondObj *bondtypes.Bond) (*schema.Bond, error) {
|
||||
// Nil record.
|
||||
if bondObj == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &Bond{
|
||||
return &schema.Bond{
|
||||
ID: bondObj.Id,
|
||||
Owner: bondObj.Owner,
|
||||
Balance: getGQLCoins(bondObj.Balance),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getAuctionBid(bid *auctiontypes.Bid) *AuctionBid {
|
||||
return &AuctionBid{
|
||||
func getAuctionBid(bid *auctiontypes.Bid) *schema.AuctionBid {
|
||||
return &schema.AuctionBid{
|
||||
BidderAddress: bid.BidderAddress,
|
||||
Status: bid.Status,
|
||||
CommitHash: bid.CommitHash,
|
||||
@ -227,14 +228,14 @@ func getAuctionBid(bid *auctiontypes.Bid) *AuctionBid {
|
||||
}
|
||||
}
|
||||
|
||||
func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Auction, error) {
|
||||
func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*schema.Auction, error) {
|
||||
if auction == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
numProviders := int(auction.NumProviders)
|
||||
|
||||
gqlAuction := Auction{
|
||||
gqlAuction := schema.Auction{
|
||||
ID: auction.Id,
|
||||
Status: auction.Status,
|
||||
OwnerAddress: auction.OwnerAddress,
|
||||
@ -253,7 +254,7 @@ func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Au
|
||||
FundsReleased: auction.FundsReleased,
|
||||
}
|
||||
|
||||
auctionBids := make([]*AuctionBid, len(bids))
|
||||
auctionBids := make([]*schema.AuctionBid, len(bids))
|
||||
for index, entry := range bids {
|
||||
auctionBids[index] = getAuctionBid(entry)
|
||||
}
|
||||
@ -263,7 +264,7 @@ func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Au
|
||||
return &gqlAuction, nil
|
||||
}
|
||||
|
||||
func toRPCValue(value *ValueInput) *registrytypes.QueryRecordsRequest_ValueInput {
|
||||
func toRPCValue(value *schema.ValueInput) *registrytypes.QueryRecordsRequest_ValueInput {
|
||||
var rpcval registrytypes.QueryRecordsRequest_ValueInput
|
||||
|
||||
switch {
|
||||
@ -295,7 +296,7 @@ func toRPCValue(value *ValueInput) *registrytypes.QueryRecordsRequest_ValueInput
|
||||
return &rpcval
|
||||
}
|
||||
|
||||
func toRPCAttributes(attrs []*KeyValueInput) []*registrytypes.QueryRecordsRequest_KeyValueInput {
|
||||
func toRPCAttributes(attrs []*schema.KeyValueInput) []*registrytypes.QueryRecordsRequest_KeyValueInput {
|
||||
kvPairs := []*registrytypes.QueryRecordsRequest_KeyValueInput{}
|
||||
|
||||
for _, value := range attrs {
|
||||
@ -310,7 +311,7 @@ func toRPCAttributes(attrs []*KeyValueInput) []*registrytypes.QueryRecordsReques
|
||||
return kvPairs
|
||||
}
|
||||
|
||||
func getAuthorityRecord(nameAuthority registrytypes.NameAuthority, auctionQueryClient auctiontypes.QueryClient) (*AuthorityRecord, error) {
|
||||
func getAuthorityRecord(nameAuthority registrytypes.NameAuthority, auctionQueryClient auctiontypes.QueryClient) (*schema.AuthorityRecord, error) {
|
||||
gqlNameAuthorityRecord, err := GetGQLNameAuthorityRecord(&nameAuthority)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -137,4 +137,4 @@ $laconicd start \
|
||||
--server.minimum-gas-prices=1$DENOM \
|
||||
--rpc.laddr="tcp://0.0.0.0:26657" \
|
||||
--grpc.address="127.0.0.1:9091" \
|
||||
--gql-server --gql-playground
|
||||
--gql.enable --gql.playground
|
||||
|
Loading…
Reference in New Issue
Block a user