Handle events
- Adds interfaces for developers to build handlers that update data in response to log events - Resolves #29
This commit is contained in:
@@ -1,77 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/filters"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/geth"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
|
||||
"github.com/vulcanize/vulcanizedb/utils"
|
||||
)
|
||||
|
||||
// addFilterCmd represents the addFilter command
|
||||
var addFilterCmd = &cobra.Command{
|
||||
Use: "addFilter",
|
||||
Short: "Adds event filter to vulcanizedb",
|
||||
Long: `An event filter is added to the vulcanize_db.
|
||||
All events matching the filter conitions will be tracked
|
||||
in vulcanizedb.
|
||||
|
||||
vulcanizedb addFilter --config config.toml --filter-filepath filter.json
|
||||
|
||||
The event filters are expected to match
|
||||
the format described in the ethereum RPC wiki:
|
||||
|
||||
https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter
|
||||
|
||||
[{
|
||||
"fromBlock": "0x1",
|
||||
"toBlock": "0x2",
|
||||
"address": "0x8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"topics": ["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
null,
|
||||
"0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"]
|
||||
}]
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
addFilter()
|
||||
},
|
||||
}
|
||||
|
||||
var filterFilepath string
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(addFilterCmd)
|
||||
|
||||
addFilterCmd.PersistentFlags().StringVar(&filterFilepath, "filter-filepath", "", "path/to/filter.json")
|
||||
addFilterCmd.MarkFlagRequired("filter-filepath")
|
||||
}
|
||||
|
||||
func addFilter() {
|
||||
if filterFilepath == "" {
|
||||
log.Fatal("filter-filepath required")
|
||||
}
|
||||
var logFilters filters.LogFilters
|
||||
blockchain := geth.NewBlockchain(ipc)
|
||||
db := utils.LoadPostgres(databaseConfig, blockchain.Node())
|
||||
filterRepository := postgres.FilterRepository{DB: &db}
|
||||
absFilePath := utils.AbsFilePath(filterFilepath)
|
||||
logFilterBytes, err := ioutil.ReadFile(absFilePath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = json.Unmarshal(logFilterBytes, &logFilters)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
for _, filter := range logFilters {
|
||||
err = filterRepository.CreateFilter(filter)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
-107
@@ -1,107 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
|
||||
"log"
|
||||
|
||||
"github.com/neelance/graphql-go"
|
||||
"github.com/neelance/graphql-go/relay"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/geth"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/graphql_server"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
|
||||
"github.com/vulcanize/vulcanizedb/utils"
|
||||
)
|
||||
|
||||
var graphqlCmd = &cobra.Command{
|
||||
Use: "graphql",
|
||||
Short: "Starts Vulcanize graphql server",
|
||||
Long: `Starts vulcanize graphql server
|
||||
and usage of using your command. For example:
|
||||
|
||||
vulcanizedb graphql --port 9090 --host localhost
|
||||
`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
schema := parseSchema()
|
||||
serve(schema)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
var (
|
||||
port int
|
||||
host string
|
||||
)
|
||||
rootCmd.AddCommand(graphqlCmd)
|
||||
|
||||
syncCmd.Flags().IntVar(&port, "port", 9090, "graphql: port")
|
||||
syncCmd.Flags().StringVar(&host, "host", "localhost", "graphql: host")
|
||||
|
||||
}
|
||||
|
||||
func parseSchema() *graphql.Schema {
|
||||
|
||||
blockchain := geth.NewBlockchain(ipc)
|
||||
db := utils.LoadPostgres(databaseConfig, blockchain.Node())
|
||||
blockRepository := &postgres.BlockRepository{DB: &db}
|
||||
logRepository := &postgres.LogRepository{DB: &db}
|
||||
filterRepository := &postgres.FilterRepository{DB: &db}
|
||||
watchedEventRepository := &postgres.WatchedEventRepository{DB: &db}
|
||||
graphQLRepositories := graphql_server.GraphQLRepositories{
|
||||
WatchedEventRepository: watchedEventRepository,
|
||||
BlockRepository: blockRepository,
|
||||
LogRepository: logRepository,
|
||||
FilterRepository: filterRepository,
|
||||
}
|
||||
schema := graphql.MustParseSchema(graphql_server.Schema, graphql_server.NewResolver(graphQLRepositories))
|
||||
return schema
|
||||
|
||||
}
|
||||
|
||||
func serve(schema *graphql.Schema) {
|
||||
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(page)
|
||||
}))
|
||||
http.Handle("/query", &relay.Handler{Schema: schema})
|
||||
|
||||
log.Fatal(http.ListenAndServe(":9090", nil))
|
||||
}
|
||||
|
||||
var page = []byte(`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/graphiql/0.10.2/graphiql.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/1.1.0/fetch.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.5.4/react-dom.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/graphiql/0.10.2/graphiql.js"></script>
|
||||
</head>
|
||||
<body style="width: 100%; height: 100%; margin: 0; overflow: hidden;">
|
||||
<div id="graphiql" style="height: 100vh;">Loading...</div>
|
||||
<script>
|
||||
function graphQLFetcher(graphQLParams) {
|
||||
return fetch("/query", {
|
||||
method: "post",
|
||||
body: JSON.stringify(graphQLParams),
|
||||
credentials: "include",
|
||||
}).then(function (response) {
|
||||
return response.text();
|
||||
}).then(function (responseBody) {
|
||||
try {
|
||||
return JSON.parse(responseBody);
|
||||
} catch (error) {
|
||||
return responseBody;
|
||||
}
|
||||
});
|
||||
}
|
||||
ReactDOM.render(
|
||||
React.createElement(GraphiQL, {fetcher: graphQLFetcher}),
|
||||
document.getElementById("graphiql")
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
+4
-4
@@ -9,10 +9,10 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/datastore"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/geth"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/history"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/repositories"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
|
||||
"github.com/vulcanize/vulcanizedb/utils"
|
||||
)
|
||||
|
||||
@@ -50,7 +50,7 @@ func init() {
|
||||
syncCmd.Flags().IntVarP(&startingBlockNumber, "starting-block-number", "s", 0, "Block number to start syncing from")
|
||||
}
|
||||
|
||||
func backFillAllBlocks(blockchain core.Blockchain, blockRepository repositories.BlockRepository, missingBlocksPopulated chan int, startingBlockNumber int64) {
|
||||
func backFillAllBlocks(blockchain core.Blockchain, blockRepository datastore.BlockRepository, missingBlocksPopulated chan int, startingBlockNumber int64) {
|
||||
go func() {
|
||||
missingBlocksPopulated <- history.PopulateMissingBlocks(blockchain, blockRepository, startingBlockNumber)
|
||||
}()
|
||||
@@ -65,7 +65,7 @@ func sync() {
|
||||
log.Fatal("geth initial: state sync not finished")
|
||||
}
|
||||
db := utils.LoadPostgres(databaseConfig, blockchain.Node())
|
||||
blockRepository := postgres.BlockRepository{DB: &db}
|
||||
blockRepository := repositories.BlockRepository{DB: &db}
|
||||
validator := history.NewBlockValidator(blockchain, blockRepository, 15)
|
||||
|
||||
missingBlocksPopulated := make(chan int)
|
||||
|
||||
Reference in New Issue
Block a user