Graphql #20

Merged
telackey merged 4 commits from graphql into master 2020-10-28 13:50:23 +00:00
9 changed files with 140 additions and 116 deletions
Showing only changes of commit 7a2ccaa8a7 - Show all commits

View File

@ -66,15 +66,23 @@ The corresponding CLI flags can be found with the `./ipld-eth-server serve --hel
ipcPath = "~/.vulcanize/vulcanize.ipc" # $SERVER_IPC_PATH ipcPath = "~/.vulcanize/vulcanize.ipc" # $SERVER_IPC_PATH
wsPath = "127.0.0.1:8081" # $SERVER_WS_PATH wsPath = "127.0.0.1:8081" # $SERVER_WS_PATH
httpPath = "127.0.0.1:8082" # $SERVER_HTTP_PATH httpPath = "127.0.0.1:8082" # $SERVER_HTTP_PATH
graphql = true # $SERVER_GRAPHQL
graphqlEndpoint = "" # $SERVER_GRAPHQL_ENDPOINT
[ethereum] [ethereum]
chainID = "1" # $ETH_CHAIN_ID chainID = "1" # $ETH_CHAIN_ID
defaultSender = "" # $ETH_DEFAULT_SENDER_ADDR defaultSender = "" # $ETH_DEFAULT_SENDER_ADDR
rpcGasCap = "1000000000000" # $ETH_RPC_GAS_CAP
httpPath = "127.0.0.1:8545" # $ETH_HTTP_PATH
nodeID = "arch1" # $ETH_NODE_ID
clientName = "Geth" # $ETH_CLIENT_NAME
genesisBlock = "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" # $ETH_GENESIS_BLOCK
networkID = "1" # $ETH_NETWORK_ID
``` ```
The `database` fields are for connecting to a Postgres database that has been/is being populated by [ipld-eth-indexer](https://github.com/vulcanize/ipld-eth-indexer). The `database` fields are for connecting to a Postgres database that has been/is being populated by [ipld-eth-indexer](https://github.com/vulcanize/ipld-eth-indexer)
The `server` fields set the paths for exposing the ipld-eth-server endpoints The `server` fields set the paths for exposing the ipld-eth-server endpoints
The `ethereum` fields set the chainID and default sender address to use for EVM simulation The `ethereum` fields set the chainID and default sender address to use for EVM simulation, and can optionally be used to configure a remote eth node to forward cache misses to
### Endpoints ### Endpoints

View File

@ -71,10 +71,17 @@ func serve() {
if err := startServers(server, serverConfig); err != nil { if err := startServers(server, serverConfig); err != nil {
logWithCommand.Fatal(err) logWithCommand.Fatal(err)
} }
graphQL, err := startGraphQL(server)
if err != nil {
logWithCommand.Fatal(err)
}
shutdown := make(chan os.Signal) shutdown := make(chan os.Signal)
signal.Notify(shutdown, os.Interrupt) signal.Notify(shutdown, os.Interrupt)
<-shutdown <-shutdown
if graphQL != nil {
graphQL.Stop()
}
server.Stop() server.Stop()
wg.Wait() wg.Wait()
} }
@ -92,29 +99,24 @@ func startServers(server s.Server, settings *s.Config) error {
} }
logWithCommand.Info("starting up HTTP server") logWithCommand.Info("starting up HTTP server")
_, _, err = srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"eth"}, nil, []string{"*"}, rpc.HTTPTimeouts{}) _, _, err = srpc.StartHTTPEndpoint(settings.HTTPEndpoint, server.APIs(), []string{"eth"}, nil, []string{"*"}, rpc.HTTPTimeouts{})
if err != nil {
return err return err
} }
return startGraphQL(server)
}
func startGraphQL(server s.Server) error { func startGraphQL(server s.Server) (graphQLServer *graphql.Service, err error) {
viper.BindEnv("server.graphql", "SERVER_GRAPHQL") viper.BindEnv("server.graphql", "SERVER_GRAPHQL")
if viper.GetBool("server.graphql") { if viper.GetBool("server.graphql") {
logWithCommand.Info("starting up GraphQL server") logWithCommand.Info("starting up GraphQL server")
viper.BindEnv("server.graphqlEndpoint", "SERVER_GRAPHQL_ENDPOINT") viper.BindEnv("server.graphqlEndpoint", "SERVER_GRAPHQL_ENDPOINT")
endPoint := viper.GetString("server.graphqlEndpoint") endPoint := viper.GetString("server.graphqlEndpoint")
if endPoint != "" { if endPoint != "" {
graphQLServer, err := graphql.New(server.Backend(), endPoint, nil, []string{"*"}, rpc.HTTPTimeouts{}) graphQLServer, err = graphql.New(server.Backend(), endPoint, nil, []string{"*"}, rpc.HTTPTimeouts{})
if err != nil { if err != nil {
return err return
} }
if err := graphQLServer.Start(nil); err != nil { err = graphQLServer.Start(nil)
return err
} }
} }
} return
return nil
} }
func init() { func init() {

2
go.mod
View File

@ -4,7 +4,7 @@ go 1.13
require ( require (
github.com/ethereum/go-ethereum v1.9.11 github.com/ethereum/go-ethereum v1.9.11
github.com/graph-gophers/graphql-go v0.0.0-20201003130358-c5bdf3b1108e // indirect github.com/graph-gophers/graphql-go v0.0.0-20201003130358-c5bdf3b1108e
github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-block-format v0.0.2
github.com/ipfs/go-cid v0.0.5 github.com/ipfs/go-cid v0.0.5
github.com/ipfs/go-ipfs-blockstore v1.0.0 github.com/ipfs/go-ipfs-blockstore v1.0.0

View File

@ -1,24 +1,18 @@
// The MIT License (MIT) // VulcanizeDB
// // Copyright © 2020 Vulcanize
// Copyright (c) 2016 Muhammed Thanish
// // This program is free software: you can redistribute it and/or modify
// Permission is hereby granted, free of charge, to any person obtaining a copy // it under the terms of the GNU Affero General Public License as published by
// of this software and associated documentation files (the "Software"), to deal // the Free Software Foundation, either version 3 of the License, or
// in the Software without restriction, including without limitation the rights // (at your option) any later version.
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is // This program is distributed in the hope that it will be useful,
// furnished to do so, subject to the following conditions: // but WITHOUT ANY WARRANTY; without even the implied warranty of
// // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// The above copyright notice and this permission notice shall be included in all // GNU Affero General Public License for more details.
// copies or substantial portions of the Software.
// // You should have received a copy of the GNU Affero General Public License
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // along with this program. If not, see <http://www.gnu.org/licenses/>.
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package graphql package graphql

View File

@ -1,18 +1,18 @@
// Copyright 2019 The go-ethereum Authors // VulcanizeDB
// This file is part of the go-ethereum library. // Copyright © 2020 Vulcanize
//
// The go-ethereum library is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by // it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details. // GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Affero General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
// Package graphql provides a GraphQL interface to Ethereum node data. // Package graphql provides a GraphQL interface to Ethereum node data.
package graphql package graphql

View File

@ -0,0 +1,35 @@
// VulcanizeDB
// Copyright © 2020 Vulcanize
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package graphql_test
import (
"io/ioutil"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/sirupsen/logrus"
)
func TestGraphQL(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "graphql test suite")
}
var _ = BeforeSuite(func() {
logrus.SetOutput(ioutil.Discard)
})

View File

@ -1,28 +1,31 @@
// Copyright 2019 The go-ethereum Authors // VulcanizeDB
// This file is part of the go-ethereum library. // Copyright © 2020 Vulcanize
//
// The go-ethereum library is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by // it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details. // GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package graphql // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package graphql_test
import ( import (
"testing" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/ipld-eth-server/pkg/graphql"
) )
func TestBuildSchema(t *testing.T) { var _ = Describe("GraphQL", func() {
// Make sure the schema can be parsed and matched up to the object model. It("Builds the schema and creates a new handler", func() {
if _, err := newHandler(nil); err != nil { _, err := graphql.NewHandler(nil)
t.Errorf("Could not construct GraphQL handler: %v", err) Expect(err).ToNot(HaveOccurred())
} })
} })

View File

@ -1,18 +1,18 @@
// Copyright 2019 The go-ethereum Authors // VulcanizeDB
// This file is part of the go-ethereum library. // Copyright © 2020 Vulcanize
//
// The go-ethereum library is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by // it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details. // GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Affero General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package graphql package graphql
@ -33,7 +33,6 @@ const schema string = `
schema { schema {
query: Query query: Query
mutation: Mutation
} }
# Account is an Ethereum account at a particular block. # Account is an Ethereum account at a particular block.
@ -206,9 +205,6 @@ const schema string = `
account(address: Address!): Account! account(address: Address!): Account!
# Call executes a local call operation at the current block's state. # Call executes a local call operation at the current block's state.
call(data: CallData!): CallResult call(data: CallData!): CallResult
# EstimateGas estimates the amount of gas that will be required for
# successful execution of a transaction at the current block's state.
estimateGas(data: CallData!): Long!
} }
# CallData represents the data associated with a local contract call. # CallData represents the data associated with a local contract call.
@ -270,23 +266,9 @@ const schema string = `
# Blocks returns all the blocks between two numbers, inclusive. If # Blocks returns all the blocks between two numbers, inclusive. If
# to is not supplied, it defaults to the most recent known block. # to is not supplied, it defaults to the most recent known block.
blocks(from: Long!, to: Long): [Block!]! blocks(from: Long!, to: Long): [Block!]!
# Pending returns the current pending state.
pending: Pending!
# Transaction returns a transaction specified by its hash. # Transaction returns a transaction specified by its hash.
transaction(hash: Bytes32!): Transaction transaction(hash: Bytes32!): Transaction
# Logs returns log entries matching the provided filter. # Logs returns log entries matching the provided filter.
logs(filter: FilterCriteria!): [Log!]! logs(filter: FilterCriteria!): [Log!]!
# GasPrice returns the node's estimate of a gas price sufficient to
# ensure a transaction is mined in a timely fashion.
gasPrice: BigInt!
# ProtocolVersion returns the current wire protocol version number.
protocolVersion: Int!
# Syncing returns information on the current synchronisation state.
syncing: SyncState
}
type Mutation {
# SendRawTransaction sends an RLP-encoded transaction to the network.
sendRawTransaction(data: Bytes!): Bytes32!
} }
` `

View File

@ -1,18 +1,18 @@
// Copyright 2019 The go-ethereum Authors // VulcanizeDB
// This file is part of the go-ethereum library. // Copyright © 2020 Vulcanize
//
// The go-ethereum library is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by // it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or // the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version. // (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details. // GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Affero General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package graphql package graphql
@ -21,11 +21,11 @@ import (
"net" "net"
"net/http" "net/http"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/graph-gophers/graphql-go" "github.com/graph-gophers/graphql-go"
"github.com/graph-gophers/graphql-go/relay" "github.com/graph-gophers/graphql-go/relay"
"github.com/sirupsen/logrus"
"github.com/vulcanize/ipld-eth-server/pkg/eth" "github.com/vulcanize/ipld-eth-server/pkg/eth"
) )
@ -62,7 +62,7 @@ func (s *Service) APIs() []rpc.API { return nil }
// layer was also initialized to spawn any goroutines required by the service. // layer was also initialized to spawn any goroutines required by the service.
func (s *Service) Start(server *p2p.Server) error { func (s *Service) Start(server *p2p.Server) error {
var err error var err error
s.handler, err = newHandler(s.backend) s.handler, err = NewHandler(s.backend)
if err != nil { if err != nil {
return err return err
} }
@ -70,13 +70,13 @@ func (s *Service) Start(server *p2p.Server) error {
return err return err
} }
go rpc.NewHTTPServer(s.cors, s.vhosts, s.timeouts, s.handler).Serve(s.listener) go rpc.NewHTTPServer(s.cors, s.vhosts, s.timeouts, s.handler).Serve(s.listener)
log.Info("GraphQL endpoint opened", "url", fmt.Sprintf("http://%s", s.endpoint)) logrus.Debugf("graphQL endpoint opened for url %s", fmt.Sprintf("http://%s", s.endpoint))
return nil return nil
} }
// newHandler returns a new `http.Handler` that will answer GraphQL queries. // newHandler returns a new `http.Handler` that will answer GraphQL queries.
// It additionally exports an interactive query browser on the / endpoint. // It additionally exports an interactive query browser on the / endpoint.
func newHandler(backend *eth.Backend) (http.Handler, error) { func NewHandler(backend *eth.Backend) (http.Handler, error) {
q := Resolver{backend} q := Resolver{backend}
s, err := graphql.ParseSchema(schema, &q) s, err := graphql.ParseSchema(schema, &q)
@ -98,7 +98,7 @@ func (s *Service) Stop() error {
if s.listener != nil { if s.listener != nil {
s.listener.Close() s.listener.Close()
s.listener = nil s.listener = nil
log.Info("GraphQL endpoint closed", "url", fmt.Sprintf("http://%s", s.endpoint)) logrus.Debugf("graphQL endpoint closed for url %s", fmt.Sprintf("http://%s", s.endpoint))
} }
return nil return nil
} }