2018-11-07 21:50:43 +00:00
// VulcanizeDB
// Copyright © 2018 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/>.
2018-11-03 19:00:25 +00:00
package cmd
import (
"bufio"
"fmt"
2018-11-07 21:50:43 +00:00
"github.com/vulcanize/vulcanizedb/pkg/core"
2018-11-03 19:00:25 +00:00
"log"
"os"
"strings"
2018-11-03 19:02:31 +00:00
"time"
2018-11-03 19:00:25 +00:00
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
"github.com/spf13/cobra"
2018-11-03 19:02:31 +00:00
"github.com/vulcanize/vulcanizedb/libraries/shared"
2018-11-03 19:00:25 +00:00
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/geth"
"github.com/vulcanize/vulcanizedb/pkg/geth/client"
vRpc "github.com/vulcanize/vulcanizedb/pkg/geth/converters/rpc"
"github.com/vulcanize/vulcanizedb/pkg/geth/node"
"github.com/vulcanize/vulcanizedb/pkg/omni/transformer"
)
// omniWatcherCmd represents the omniWatcher command
var omniWatcherCmd = & cobra . Command {
Use : "omniWatcher" ,
Short : "Watches events at the provided contract address" ,
Long : ` Uses input contract address and event filters to watch events
Expects an ethereum node to be running
Expects an archival node synced into vulcanizeDB
Requires a . toml config file :
[ database ]
name = "vulcanize_public"
hostname = "localhost"
port = 5432
[ client ]
ipcPath = "/Users/user/Library/Ethereum/geth.ipc"
` ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
omniWatcher ( )
} ,
}
func omniWatcher ( ) {
2018-11-03 19:02:31 +00:00
if contractAddress == "" && len ( contractAddresses ) == 0 {
2018-11-03 19:00:25 +00:00
log . Fatal ( "Contract address required" )
}
2018-11-03 19:02:31 +00:00
if len ( contractEvents ) == 0 || len ( contractMethods ) == 0 {
2018-11-03 19:00:25 +00:00
var str string
for str != "y" {
reader := bufio . NewReader ( os . Stdin )
2018-11-03 19:02:31 +00:00
if len ( contractEvents ) == 0 && len ( contractMethods ) == 0 {
2018-11-07 21:50:43 +00:00
fmt . Print ( "Warning: no events or methods specified.\n Proceed to watch every event and poll no methods? (Y/n)\n> " )
2018-11-03 19:02:31 +00:00
} else if len ( contractEvents ) == 0 {
2018-11-07 21:50:43 +00:00
fmt . Print ( "Warning: no events specified.\n Proceed to watch every event? (Y/n)\n> " )
2018-11-03 19:02:31 +00:00
} else {
2018-11-07 21:50:43 +00:00
fmt . Print ( "Warning: no methods specified.\n Proceed to poll no methods? (Y/n)\n> " )
2018-11-03 19:02:31 +00:00
}
2018-11-03 19:00:25 +00:00
resp , err := reader . ReadBytes ( '\n' )
if err != nil {
log . Fatal ( err )
}
str = strings . ToLower ( string ( resp ) )
if str == "n" {
return
}
}
}
2018-11-04 21:26:39 +00:00
ticker := time . NewTicker ( 5 * time . Second )
defer ticker . Stop ( )
2018-11-07 21:50:43 +00:00
blockChain , db := setupBCandDB ( )
2018-11-03 19:00:25 +00:00
2018-11-07 21:50:43 +00:00
t := transformer . NewTransformer ( network , blockChain , db )
2018-11-03 19:02:31 +00:00
contractAddresses = append ( contractAddresses , contractAddress )
for _ , addr := range contractAddresses {
2018-11-04 21:26:39 +00:00
t . SetEvents ( addr , contractEvents )
t . SetMethods ( addr , contractMethods )
2018-11-07 21:50:43 +00:00
t . SetEventAddrs ( addr , eventAddrs )
t . SetMethodAddrs ( addr , methodAddrs )
t . SetRange ( addr , [ 2 ] int64 { startingBlockNumber , endingBlockNumber } )
2018-11-03 19:02:31 +00:00
}
2018-11-03 19:00:25 +00:00
2018-11-07 21:50:43 +00:00
err := t . Init ( )
2018-11-03 19:00:25 +00:00
if err != nil {
2018-11-03 19:02:31 +00:00
log . Fatal ( fmt . Sprintf ( "Failed to initialized transformer\r\nerr: %v\r\n" , err ) )
2018-11-03 19:00:25 +00:00
}
2018-11-03 19:02:31 +00:00
w := shared . Watcher { }
w . AddTransformer ( t )
for range ticker . C {
w . Execute ( )
}
2018-11-03 19:00:25 +00:00
}
func init ( ) {
rootCmd . AddCommand ( omniWatcherCmd )
omniWatcherCmd . Flags ( ) . StringVarP ( & contractAddress , "contract-address" , "a" , "" , "Single address to generate watchers for" )
2018-11-07 21:50:43 +00:00
omniWatcherCmd . Flags ( ) . StringArrayVarP ( & contractAddresses , "contract-addresses" , "l" , [ ] string { } , "list of addresses to use; warning: watcher targets the same events and methods for each address" )
2018-11-03 19:02:31 +00:00
omniWatcherCmd . Flags ( ) . StringArrayVarP ( & contractEvents , "contract-events" , "e" , [ ] string { } , "Subset of events to watch; by default all events are watched" )
2018-11-07 21:50:43 +00:00
omniWatcherCmd . Flags ( ) . StringArrayVarP ( & contractEvents , "contract-methods" , "m" , nil , "Subset of methods to poll; by default no methods are polled" )
omniWatcherCmd . Flags ( ) . StringArrayVarP ( & eventAddrs , "event-filter-addresses" , "f" , [ ] string { } , "Account addresses to persist event data for; default is to persist for all found token holder addresses" )
omniWatcherCmd . Flags ( ) . StringArrayVarP ( & methodAddrs , "method-filter-addresses" , "g" , [ ] string { } , "Account addresses to poll methods with; default is to poll with all found token holder addresses" )
2018-11-03 19:00:25 +00:00
omniWatcherCmd . Flags ( ) . StringVarP ( & network , "network" , "n" , "" , ` Network the contract is deployed on; options: "ropsten", "kovan", and "rinkeby"; default is mainnet" ` )
2018-11-07 21:50:43 +00:00
omniWatcherCmd . Flags ( ) . Int64VarP ( & startingBlockNumber , "starting-block-number" , "s" , 0 , "Block to begin watching- default is first block the contract exists" )
omniWatcherCmd . Flags ( ) . Int64VarP ( & startingBlockNumber , "ending-block-number" , "d" , - 1 , "Block to end watching- default is most recent block" )
}
func setupBCandDB ( ) ( core . BlockChain , * postgres . DB ) {
rawRpcClient , err := rpc . Dial ( ipc )
if err != nil {
log . Fatal ( fmt . Sprintf ( "Failed to initialize rpc client\r\nerr: %v\r\n" , err ) )
}
rpcClient := client . NewRpcClient ( rawRpcClient , ipc )
ethClient := ethclient . NewClient ( rawRpcClient )
cli := client . NewEthClient ( ethClient )
n := node . MakeNode ( rpcClient )
transactionConverter := vRpc . NewRpcTransactionConverter ( ethClient )
blockChain := geth . NewBlockChain ( cli , n , transactionConverter )
db , err := postgres . NewDB ( databaseConfig , blockChain . Node ( ) )
if err != nil {
log . Fatal ( fmt . Sprintf ( "Failed to initialize database\r\nerr: %v\r\n" , err ) )
}
return blockChain , db
2018-11-03 19:00:25 +00:00
}