diff --git a/graphql/graphql_test.go b/graphql/graphql_test.go index ca864d5fb2..11fb72eed8 100644 --- a/graphql/graphql_test.go +++ b/graphql/graphql_test.go @@ -23,6 +23,7 @@ import ( "io" "math/big" "net/http" + "slices" "strings" "testing" "time" @@ -60,6 +61,65 @@ func TestBuildSchema(t *testing.T) { } } +func TestSyncStateSchemaFields(t *testing.T) { + ddir := t.TempDir() + conf := node.DefaultConfig + conf.DataDir = ddir + stack, err := node.New(&conf) + if err != nil { + t.Fatalf("could not create new node: %v", err) + } + defer stack.Close() + + h, err := newHandler(stack, nil, nil, []string{}, []string{}) + if err != nil { + t.Fatalf("could not construct GraphQL handler: %v", err) + } + res := h.Schema.Exec(context.Background(), `{ __type(name: "SyncState") { fields { name } } }`, "", nil) + if len(res.Errors) > 0 { + t.Fatalf("failed to execute introspection query: %v", res.Errors) + } + var got struct { + Type struct { + Fields []struct { + Name string `json:"name"` + } `json:"fields"` + } `json:"__type"` + } + if err := json.Unmarshal(res.Data, &got); err != nil { + t.Fatalf("failed to decode introspection response: %v", err) + } + names := make([]string, 0, len(got.Type.Fields)) + for _, field := range got.Type.Fields { + names = append(names, field.Name) + } + want := []string{ + "startingBlock", + "currentBlock", + "highestBlock", + "syncedAccounts", + "syncedAccountBytes", + "syncedBytecodes", + "syncedBytecodeBytes", + "syncedStorage", + "syncedStorageBytes", + "healedTrienodes", + "healedTrienodeBytes", + "healedBytecodes", + "healedBytecodeBytes", + "healingTrienodes", + "healingBytecode", + "txIndexFinishedBlocks", + "txIndexRemainingBlocks", + "stateIndexRemaining", + } + for _, field := range want { + if !slices.Contains(names, field) { + t.Fatalf("SyncState schema is missing field %q", field) + } + } +} + // Tests that a graphQL request is successfully handled when graphql is enabled on the specified endpoint func TestGraphQLBlockSerialization(t *testing.T) { stack := createNode(t) diff --git a/graphql/schema.go b/graphql/schema.go index 15e4557915..5fd321f88e 100644 --- a/graphql/schema.go +++ b/graphql/schema.go @@ -342,6 +342,36 @@ const schema string = ` currentBlock: Long! # HighestBlock is the latest known block number. highestBlock: Long! + # SyncedAccounts is the number of accounts downloaded. + syncedAccounts: Long! + # SyncedAccountBytes is the number of account trie bytes persisted to disk. + syncedAccountBytes: Long! + # SyncedBytecodes is the number of bytecodes downloaded. + syncedBytecodes: Long! + # SyncedBytecodeBytes is the number of bytecode bytes downloaded. + syncedBytecodeBytes: Long! + # SyncedStorage is the number of storage slots downloaded. + syncedStorage: Long! + # SyncedStorageBytes is the number of storage trie bytes persisted to disk. + syncedStorageBytes: Long! + # HealedTrienodes is the number of state trie nodes downloaded. + healedTrienodes: Long! + # HealedTrienodeBytes is the number of state trie bytes persisted to disk. + healedTrienodeBytes: Long! + # HealedBytecodes is the number of bytecodes downloaded. + healedBytecodes: Long! + # HealedBytecodeBytes is the number of bytecodes persisted to disk. + healedBytecodeBytes: Long! + # HealingTrienodes is the number of state trie nodes pending. + healingTrienodes: Long! + # HealingBytecode is the number of bytecodes pending. + healingBytecode: Long! + # TxIndexFinishedBlocks is the number of blocks whose transactions are indexed. + txIndexFinishedBlocks: Long! + # TxIndexRemainingBlocks is the number of blocks whose transactions are not indexed yet. + txIndexRemainingBlocks: Long! + # StateIndexRemaining is the number of blocks whose state histories are not indexed yet. + stateIndexRemaining: Long! } # Pending represents the current pending state.