PR fixes; remove all infura token references and setup travis to use encrypted env
variable; rest of the ethjson_rpc dependent tests extracted to integration_test
This commit is contained in:
+29
-28
@@ -19,6 +19,7 @@ package config
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/geth"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -65,20 +66,20 @@ type ContractConfig struct {
|
||||
Piping map[string]bool
|
||||
}
|
||||
|
||||
func (oc *ContractConfig) PrepConfig() {
|
||||
func (contractConfig *ContractConfig) PrepConfig() {
|
||||
addrs := viper.GetStringSlice("contract.addresses")
|
||||
oc.Network = viper.GetString("contract.network")
|
||||
oc.Addresses = make(map[string]bool, len(addrs))
|
||||
oc.Abis = make(map[string]string, len(addrs))
|
||||
oc.Methods = make(map[string][]string, len(addrs))
|
||||
oc.Events = make(map[string][]string, len(addrs))
|
||||
oc.MethodArgs = make(map[string][]string, len(addrs))
|
||||
oc.EventArgs = make(map[string][]string, len(addrs))
|
||||
oc.StartingBlocks = make(map[string]int64, len(addrs))
|
||||
oc.Piping = make(map[string]bool, len(addrs))
|
||||
contractConfig.Network = viper.GetString("contract.network")
|
||||
contractConfig.Addresses = make(map[string]bool, len(addrs))
|
||||
contractConfig.Abis = make(map[string]string, len(addrs))
|
||||
contractConfig.Methods = make(map[string][]string, len(addrs))
|
||||
contractConfig.Events = make(map[string][]string, len(addrs))
|
||||
contractConfig.MethodArgs = make(map[string][]string, len(addrs))
|
||||
contractConfig.EventArgs = make(map[string][]string, len(addrs))
|
||||
contractConfig.StartingBlocks = make(map[string]int64, len(addrs))
|
||||
contractConfig.Piping = make(map[string]bool, len(addrs))
|
||||
// De-dupe addresses
|
||||
for _, addr := range addrs {
|
||||
oc.Addresses[strings.ToLower(addr)] = true
|
||||
contractConfig.Addresses[strings.ToLower(addr)] = true
|
||||
}
|
||||
|
||||
// Iterate over addresses to pull out config info for each contract
|
||||
@@ -87,26 +88,29 @@ func (oc *ContractConfig) PrepConfig() {
|
||||
|
||||
// Get and check abi
|
||||
var abi string
|
||||
_, abiOK := transformer["abi"]
|
||||
abiInterface, abiOK := transformer["abi"]
|
||||
if !abiOK {
|
||||
log.Warnf("contract %s not configured with an ABI, will attempt to fetch it from Etherscan\r\n", addr)
|
||||
} else {
|
||||
abiInterface := transformer["abi"]
|
||||
abi, abiOK = abiInterface.(string)
|
||||
if !abiOK {
|
||||
log.Fatal(addr, "transformer `abi` not of type []string")
|
||||
}
|
||||
}
|
||||
oc.Abis[strings.ToLower(addr)] = abi
|
||||
if abi != "" {
|
||||
if _, abiErr := geth.ParseAbi(abi); abiErr != nil {
|
||||
log.Fatal(addr, "transformer `abi` not valid JSON")
|
||||
}
|
||||
}
|
||||
contractConfig.Abis[strings.ToLower(addr)] = abi
|
||||
|
||||
// Get and check events
|
||||
events := make([]string, 0)
|
||||
_, eventsOK := transformer["events"]
|
||||
eventsInterface, eventsOK := transformer["events"]
|
||||
if !eventsOK {
|
||||
log.Warnf("contract %s not configured with a list of events to watch, will watch all events\r\n", addr)
|
||||
events = []string{}
|
||||
} else {
|
||||
eventsInterface := transformer["events"]
|
||||
eventsI, eventsOK := eventsInterface.([]interface{})
|
||||
if !eventsOK {
|
||||
log.Fatal(addr, "transformer `events` not of type []string\r\n")
|
||||
@@ -119,16 +123,15 @@ func (oc *ContractConfig) PrepConfig() {
|
||||
events = append(events, str)
|
||||
}
|
||||
}
|
||||
oc.Events[strings.ToLower(addr)] = events
|
||||
contractConfig.Events[strings.ToLower(addr)] = events
|
||||
|
||||
// Get and check methods
|
||||
methods := make([]string, 0)
|
||||
_, methodsOK := transformer["methods"]
|
||||
methodsInterface, methodsOK := transformer["methods"]
|
||||
if !methodsOK {
|
||||
log.Warnf("contract %s not configured with a list of methods to poll, will not poll any methods\r\n", addr)
|
||||
methods = []string{}
|
||||
} else {
|
||||
methodsInterface := transformer["methods"]
|
||||
methodsI, methodsOK := methodsInterface.([]interface{})
|
||||
if !methodsOK {
|
||||
log.Fatal(addr, "transformer `methods` not of type []string\r\n")
|
||||
@@ -141,16 +144,15 @@ func (oc *ContractConfig) PrepConfig() {
|
||||
methods = append(methods, str)
|
||||
}
|
||||
}
|
||||
oc.Methods[strings.ToLower(addr)] = methods
|
||||
contractConfig.Methods[strings.ToLower(addr)] = methods
|
||||
|
||||
// Get and check eventArgs
|
||||
eventArgs := make([]string, 0)
|
||||
_, eventArgsOK := transformer["eventArgs"]
|
||||
eventArgsInterface, eventArgsOK := transformer["eventArgs"]
|
||||
if !eventArgsOK {
|
||||
log.Warnf("contract %s not configured with a list of event arguments to filter for, will not filter events for specific emitted values\r\n", addr)
|
||||
eventArgs = []string{}
|
||||
} else {
|
||||
eventArgsInterface := transformer["eventArgs"]
|
||||
eventArgsI, eventArgsOK := eventArgsInterface.([]interface{})
|
||||
if !eventArgsOK {
|
||||
log.Fatal(addr, "transformer `eventArgs` not of type []string\r\n")
|
||||
@@ -163,16 +165,15 @@ func (oc *ContractConfig) PrepConfig() {
|
||||
eventArgs = append(eventArgs, str)
|
||||
}
|
||||
}
|
||||
oc.EventArgs[strings.ToLower(addr)] = eventArgs
|
||||
contractConfig.EventArgs[strings.ToLower(addr)] = eventArgs
|
||||
|
||||
// Get and check methodArgs
|
||||
methodArgs := make([]string, 0)
|
||||
_, methodArgsOK := transformer["methodArgs"]
|
||||
methodArgsInterface, methodArgsOK := transformer["methodArgs"]
|
||||
if !methodArgsOK {
|
||||
log.Warnf("contract %s not configured with a list of method argument values to poll with, will poll methods with all available arguments\r\n", addr)
|
||||
methodArgs = []string{}
|
||||
} else {
|
||||
methodArgsInterface := transformer["methodArgs"]
|
||||
methodArgsI, methodArgsOK := methodArgsInterface.([]interface{})
|
||||
if !methodArgsOK {
|
||||
log.Fatal(addr, "transformer `methodArgs` not of type []string\r\n")
|
||||
@@ -185,7 +186,7 @@ func (oc *ContractConfig) PrepConfig() {
|
||||
methodArgs = append(methodArgs, str)
|
||||
}
|
||||
}
|
||||
oc.MethodArgs[strings.ToLower(addr)] = methodArgs
|
||||
contractConfig.MethodArgs[strings.ToLower(addr)] = methodArgs
|
||||
|
||||
// Get and check startingBlock
|
||||
startInterface, startOK := transformer["startingblock"]
|
||||
@@ -196,7 +197,7 @@ func (oc *ContractConfig) PrepConfig() {
|
||||
if !startOK {
|
||||
log.Fatal(addr, "transformer `startingBlock` not of type int\r\n")
|
||||
}
|
||||
oc.StartingBlocks[strings.ToLower(addr)] = start
|
||||
contractConfig.StartingBlocks[strings.ToLower(addr)] = start
|
||||
|
||||
// Get pipping
|
||||
var piping bool
|
||||
@@ -211,6 +212,6 @@ func (oc *ContractConfig) PrepConfig() {
|
||||
log.Fatal(addr, "transformer `piping` not of type bool\r\n")
|
||||
}
|
||||
}
|
||||
oc.Piping[strings.ToLower(addr)] = piping
|
||||
contractConfig.Piping[strings.ToLower(addr)] = piping
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,10 @@ func (c *Converter) Update(info *contract.Contract) {
|
||||
|
||||
// Convert the given watched event log into a types.Log for the given event
|
||||
func (c *Converter) Convert(watchedEvent core.WatchedEvent, event types.Event) (*types.Log, error) {
|
||||
contract := bind.NewBoundContract(common.HexToAddress(c.ContractInfo.Address), c.ContractInfo.ParsedAbi, nil, nil, nil)
|
||||
boundContract := bind.NewBoundContract(common.HexToAddress(c.ContractInfo.Address), c.ContractInfo.ParsedAbi, nil, nil, nil)
|
||||
values := make(map[string]interface{})
|
||||
log := helpers.ConvertToLog(watchedEvent)
|
||||
err := contract.UnpackLogIntoMap(values, event.Name, log)
|
||||
err := boundContract.UnpackLogIntoMap(values, event.Name, log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -36,37 +36,40 @@ import (
|
||||
// Requires a fully synced vDB and a running eth node (or infura)
|
||||
type Transformer struct {
|
||||
// Database interfaces
|
||||
datastore.FilterRepository // Log filters repo; accepts filters generated by Contract.GenerateFilters()
|
||||
datastore.WatchedEventRepository // Watched event log views, created by the log filters
|
||||
repository.EventRepository // Holds transformed watched event log data
|
||||
FilterRepository datastore.FilterRepository // Log filters repo; accepts filters generated by Contract.GenerateFilters()
|
||||
WatchedEventRepository datastore.WatchedEventRepository // Watched event log views, created by the log filters
|
||||
TransformedEventRepository repository.EventRepository // Holds transformed watched event log data
|
||||
|
||||
// Pre-processing interfaces
|
||||
parser.Parser // Parses events and methods out of contract abi fetched using contract address
|
||||
retriever.BlockRetriever // Retrieves first block for contract and current block height
|
||||
Parser parser.Parser // Parses events and methods out of contract abi fetched using contract address
|
||||
Retriever retriever.BlockRetriever // Retrieves first block for contract and current block height
|
||||
|
||||
// Processing interfaces
|
||||
converter.ConverterInterface // Converts watched event logs into custom log
|
||||
poller.Poller // Polls methods using contract's token holder addresses and persists them using method datastore
|
||||
Converter converter.ConverterInterface // Converts watched event logs into custom log
|
||||
Poller poller.Poller // Polls methods using contract's token holder addresses and persists them using method datastore
|
||||
|
||||
// Store contract configuration information
|
||||
Config config.ContractConfig
|
||||
|
||||
// Store contract info as mapping to contract address
|
||||
Contracts map[string]*contract.Contract
|
||||
|
||||
// Latest block in the block repository
|
||||
LastBlock int64
|
||||
}
|
||||
|
||||
// Transformer takes in config for blockchain, database, and network id
|
||||
func NewTransformer(con config.ContractConfig, BC core.BlockChain, DB *postgres.DB) *Transformer {
|
||||
return &Transformer{
|
||||
Poller: poller.NewPoller(BC, DB, types.FullSync),
|
||||
Parser: parser.NewParser(con.Network),
|
||||
BlockRetriever: retriever.NewBlockRetriever(DB),
|
||||
ConverterInterface: &converter.Converter{},
|
||||
Contracts: map[string]*contract.Contract{},
|
||||
WatchedEventRepository: repositories.WatchedEventRepository{DB: DB},
|
||||
FilterRepository: repositories.FilterRepository{DB: DB},
|
||||
EventRepository: repository.NewEventRepository(DB, types.FullSync),
|
||||
Config: con,
|
||||
Poller: poller.NewPoller(BC, DB, types.FullSync),
|
||||
Parser: parser.NewParser(con.Network),
|
||||
Retriever: retriever.NewBlockRetriever(DB),
|
||||
Converter: &converter.Converter{},
|
||||
Contracts: map[string]*contract.Contract{},
|
||||
WatchedEventRepository: repositories.WatchedEventRepository{DB: DB},
|
||||
FilterRepository: repositories.FilterRepository{DB: DB},
|
||||
TransformedEventRepository: repository.NewEventRepository(DB, types.FullSync),
|
||||
Config: con,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,15 +95,10 @@ func (tr *Transformer) Init() error {
|
||||
}
|
||||
|
||||
// Get first block and most recent block number in the header repo
|
||||
firstBlock, err := tr.BlockRetriever.RetrieveFirstBlock(contractAddr)
|
||||
firstBlock, err := tr.Retriever.RetrieveFirstBlock(contractAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lastBlock, err := tr.BlockRetriever.RetrieveMostRecentBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set to specified range if it falls within the bounds
|
||||
if firstBlock < tr.Config.StartingBlocks[contractAddr] {
|
||||
firstBlock = tr.Config.StartingBlocks[contractAddr]
|
||||
@@ -108,7 +106,7 @@ func (tr *Transformer) Init() error {
|
||||
|
||||
// Get contract name if it has one
|
||||
var name = new(string)
|
||||
tr.FetchContractData(tr.Abi(), contractAddr, "name", nil, name, lastBlock)
|
||||
tr.Poller.FetchContractData(tr.Parser.Abi(), contractAddr, "name", nil, name, tr.LastBlock)
|
||||
|
||||
// Remove any potential accidental duplicate inputs in arg filter values
|
||||
eventArgs := map[string]bool{}
|
||||
@@ -128,7 +126,6 @@ func (tr *Transformer) Init() error {
|
||||
Abi: tr.Parser.Abi(),
|
||||
ParsedAbi: tr.Parser.ParsedAbi(),
|
||||
StartingBlock: firstBlock,
|
||||
LastBlock: lastBlock,
|
||||
Events: tr.Parser.GetEvents(tr.Config.Events[contractAddr]),
|
||||
Methods: tr.Parser.GetSelectMethods(tr.Config.Methods[contractAddr]),
|
||||
FilterArgs: eventArgs,
|
||||
@@ -144,7 +141,7 @@ func (tr *Transformer) Init() error {
|
||||
|
||||
// Iterate over filters and push them to the repo using filter repository interface
|
||||
for _, filter := range info.Filters {
|
||||
err = tr.CreateFilter(filter)
|
||||
err = tr.FilterRepository.CreateFilter(filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -154,6 +151,13 @@ func (tr *Transformer) Init() error {
|
||||
tr.Contracts[contractAddr] = info
|
||||
}
|
||||
|
||||
// Get the most recent block number in the block repo
|
||||
var err error
|
||||
tr.LastBlock, err = tr.Retriever.RetrieveMostRecentBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -169,11 +173,11 @@ func (tr *Transformer) Execute() error {
|
||||
// Iterate through all internal contracts
|
||||
for _, con := range tr.Contracts {
|
||||
// Update converter with current contract
|
||||
tr.Update(con)
|
||||
tr.Converter.Update(con)
|
||||
|
||||
// Iterate through contract filters and get watched event logs
|
||||
for eventSig, filter := range con.Filters {
|
||||
watchedEvents, err := tr.GetWatchedEvents(filter.Name)
|
||||
watchedEvents, err := tr.WatchedEventRepository.GetWatchedEvents(filter.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -181,7 +185,7 @@ func (tr *Transformer) Execute() error {
|
||||
// Iterate over watched event logs
|
||||
for _, we := range watchedEvents {
|
||||
// Convert them to our custom log type
|
||||
cstm, err := tr.ConverterInterface.Convert(*we, con.Events[eventSig])
|
||||
cstm, err := tr.Converter.Convert(*we, con.Events[eventSig])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -191,7 +195,7 @@ func (tr *Transformer) Execute() error {
|
||||
|
||||
// If log is not empty, immediately persist in repo
|
||||
// Run this in seperate goroutine?
|
||||
err = tr.PersistLogs([]types.Log{*cstm}, con.Events[eventSig], con.Address, con.Name)
|
||||
err = tr.TransformedEventRepository.PersistLogs([]types.Log{*cstm}, con.Events[eventSig], con.Address, con.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -201,12 +205,19 @@ func (tr *Transformer) Execute() error {
|
||||
// After persisting all watched event logs
|
||||
// poller polls select contract methods
|
||||
// and persists the results into custom pg tables
|
||||
// Run this in seperate goroutine?
|
||||
if err := tr.PollContract(*con); err != nil {
|
||||
if err := tr.Poller.PollContract(*con, tr.LastBlock); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// At the end of a transformation cycle, and before the next
|
||||
// update the latest block from the block repo
|
||||
var err error
|
||||
tr.LastBlock, err = tr.Retriever.RetrieveMostRecentBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package transformer_test
|
||||
|
||||
import (
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/helpers/test_helpers/mocks"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
@@ -27,6 +26,7 @@ import (
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/full/retriever"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/full/transformer"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/contract"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/helpers/test_helpers/mocks"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/parser"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/poller"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/types"
|
||||
@@ -67,7 +67,7 @@ var _ = Describe("Transformer", func() {
|
||||
Expect(ok).To(Equal(true))
|
||||
|
||||
Expect(c.StartingBlock).To(Equal(firstBlock))
|
||||
Expect(c.LastBlock).To(Equal(mostRecentBlock))
|
||||
Expect(t.LastBlock).To(Equal(mostRecentBlock))
|
||||
Expect(c.Abi).To(Equal(fakeAbi))
|
||||
Expect(c.Name).To(Equal(fakeContractName))
|
||||
Expect(c.Address).To(Equal(fakeAddress))
|
||||
@@ -90,7 +90,7 @@ func getTransformer(blockRetriever retriever.BlockRetriever, parsr parser.Parser
|
||||
return transformer.Transformer{
|
||||
FilterRepository: &fakes.MockFilterRepository{},
|
||||
Parser: parsr,
|
||||
BlockRetriever: blockRetriever,
|
||||
Retriever: blockRetriever,
|
||||
Poller: pollr,
|
||||
Contracts: map[string]*contract.Contract{},
|
||||
Config: mocks.MockConfig,
|
||||
|
||||
@@ -48,7 +48,7 @@ func (c *Converter) Update(info *contract.Contract) {
|
||||
|
||||
// Convert the given watched event log into a types.Log for the given event
|
||||
func (c *Converter) Convert(logs []gethTypes.Log, event types.Event, headerID int64) ([]types.Log, error) {
|
||||
contract := bind.NewBoundContract(common.HexToAddress(c.ContractInfo.Address), c.ContractInfo.ParsedAbi, nil, nil, nil)
|
||||
boundContract := bind.NewBoundContract(common.HexToAddress(c.ContractInfo.Address), c.ContractInfo.ParsedAbi, nil, nil, nil)
|
||||
returnLogs := make([]types.Log, 0, len(logs))
|
||||
for _, log := range logs {
|
||||
values := make(map[string]interface{})
|
||||
@@ -57,7 +57,7 @@ func (c *Converter) Convert(logs []gethTypes.Log, event types.Event, headerID in
|
||||
values[field.Name] = i
|
||||
}
|
||||
|
||||
err := contract.UnpackLogIntoMap(values, event.Name, log)
|
||||
err := boundContract.UnpackLogIntoMap(values, event.Name, log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
"github.com/hashicorp/golang-lru"
|
||||
|
||||
@@ -130,7 +130,7 @@ func (r *headerRepository) MarkHeaderCheckedForAll(headerID int64, ids []string)
|
||||
|
||||
// Marks all of the provided headers checked for each of the provided column ids
|
||||
func (r *headerRepository) MarkHeadersCheckedForAll(headers []core.Header, ids []string) error {
|
||||
tx, err := r.db.Begin()
|
||||
tx, err := r.db.Beginx()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -280,7 +280,7 @@ func (r *headerRepository) CheckCache(key string) (interface{}, bool) {
|
||||
}
|
||||
|
||||
// Used to mark a header checked as part of some external transaction so as to group into one commit
|
||||
func MarkHeaderCheckedInTransaction(headerID int64, tx *sql.Tx, eventID string) error {
|
||||
func MarkHeaderCheckedInTransaction(headerID int64, tx *sqlx.Tx, eventID string) error {
|
||||
_, err := tx.Exec(`INSERT INTO public.checked_headers (header_id, `+eventID+`)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT (header_id) DO
|
||||
|
||||
@@ -32,7 +32,6 @@ import (
|
||||
|
||||
var _ = Describe("Repository", func() {
|
||||
var db *postgres.DB
|
||||
var bc core.BlockChain
|
||||
var contractHeaderRepo repository.HeaderRepository // contract_watcher light header repository
|
||||
var coreHeaderRepo repositories.HeaderRepository // pkg/datastore header repository
|
||||
var eventIDs = []string{
|
||||
@@ -47,7 +46,7 @@ var _ = Describe("Repository", func() {
|
||||
}
|
||||
|
||||
BeforeEach(func() {
|
||||
db, bc = test_helpers.SetupDBandBC()
|
||||
db, _ = test_helpers.SetupDBandBC()
|
||||
contractHeaderRepo = repository.NewHeaderRepository(db)
|
||||
coreHeaderRepo = repositories.NewHeaderRepository(db)
|
||||
})
|
||||
@@ -205,7 +204,7 @@ var _ = Describe("Repository", func() {
|
||||
})
|
||||
|
||||
It("Returns at most 100 headers", func() {
|
||||
add102Headers(coreHeaderRepo, bc)
|
||||
add102Headers(coreHeaderRepo)
|
||||
err := contractHeaderRepo.AddCheckColumns(eventIDs)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
@@ -359,11 +358,11 @@ func addDiscontinuousHeaders(coreHeaderRepo repositories.HeaderRepository) {
|
||||
coreHeaderRepo.CreateOrUpdateHeader(mocks.MockHeader4)
|
||||
}
|
||||
|
||||
func add102Headers(coreHeaderRepo repositories.HeaderRepository, blockChain core.BlockChain) {
|
||||
func add102Headers(coreHeaderRepo repositories.HeaderRepository) {
|
||||
baseHeader := mocks.MockHeader1
|
||||
for i := 6194632; i < 6194733; i++ {
|
||||
header, err := blockChain.GetHeaderByNumber(int64(i))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = coreHeaderRepo.CreateOrUpdateHeader(header)
|
||||
_, err := coreHeaderRepo.CreateOrUpdateHeader(baseHeader)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
baseHeader.BlockNumber++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ package transformer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/config"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/config"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/light/converter"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/light/fetcher"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/light/repository"
|
||||
@@ -40,17 +40,17 @@ import (
|
||||
// Requires a light synced vDB (headers) and a running eth node (or infura)
|
||||
type Transformer struct {
|
||||
// Database interfaces
|
||||
srep.EventRepository // Holds transformed watched event log data
|
||||
repository.HeaderRepository // Interface for interaction with header repositories
|
||||
EventRepository srep.EventRepository // Holds transformed watched event log data
|
||||
HeaderRepository repository.HeaderRepository // Interface for interaction with header repositories
|
||||
|
||||
// Pre-processing interfaces
|
||||
parser.Parser // Parses events and methods out of contract abi fetched using contract address
|
||||
retriever.BlockRetriever // Retrieves first block for contract and current block height
|
||||
Parser parser.Parser // Parses events and methods out of contract abi fetched using contract address
|
||||
Retriever retriever.BlockRetriever // Retrieves first block for contract
|
||||
|
||||
// Processing interfaces
|
||||
fetcher.Fetcher // Fetches event logs, using header hashes
|
||||
converter.ConverterInterface // Converts watched event logs into custom log
|
||||
poller.Poller // Polls methods using arguments collected from events and persists them using a method datastore
|
||||
Fetcher fetcher.Fetcher // Fetches event logs, using header hashes
|
||||
Converter converter.ConverterInterface // Converts watched event logs into custom log
|
||||
Poller poller.Poller // Polls methods using arguments collected from events and persists them using a method datastore
|
||||
|
||||
// Store contract configuration information
|
||||
Config config.ContractConfig
|
||||
@@ -64,7 +64,7 @@ type Transformer struct {
|
||||
sortedMethodIds map[string][]string // Map to sort method column ids by contract, for post fetch method polling
|
||||
eventIds []string // Holds event column ids across all contract, for batch fetching of headers
|
||||
eventFilters []common.Hash // Holds topic0 hashes across all contracts, for batch fetching of logs
|
||||
start int64 // Hold the lowest starting block and the highest ending block
|
||||
Start int64 // Hold the lowest starting block and the highest ending block
|
||||
}
|
||||
|
||||
// Order-of-operations:
|
||||
@@ -77,15 +77,15 @@ type Transformer struct {
|
||||
func NewTransformer(con config.ContractConfig, bc core.BlockChain, db *postgres.DB) *Transformer {
|
||||
|
||||
return &Transformer{
|
||||
Poller: poller.NewPoller(bc, db, types.LightSync),
|
||||
Fetcher: fetcher.NewFetcher(bc),
|
||||
Parser: parser.NewParser(con.Network),
|
||||
HeaderRepository: repository.NewHeaderRepository(db),
|
||||
BlockRetriever: retriever.NewBlockRetriever(db),
|
||||
ConverterInterface: &converter.Converter{},
|
||||
Contracts: map[string]*contract.Contract{},
|
||||
EventRepository: srep.NewEventRepository(db, types.LightSync),
|
||||
Config: con,
|
||||
Poller: poller.NewPoller(bc, db, types.LightSync),
|
||||
Fetcher: fetcher.NewFetcher(bc),
|
||||
Parser: parser.NewParser(con.Network),
|
||||
HeaderRepository: repository.NewHeaderRepository(db),
|
||||
Retriever: retriever.NewBlockRetriever(db),
|
||||
Converter: &converter.Converter{},
|
||||
Contracts: map[string]*contract.Contract{},
|
||||
EventRepository: srep.NewEventRepository(db, types.LightSync),
|
||||
Config: con,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func (tr *Transformer) Init() error {
|
||||
tr.sortedMethodIds = make(map[string][]string) // Map to sort method column ids by contract, for post fetch method polling
|
||||
tr.eventIds = make([]string, 0) // Holds event column ids across all contract, for batch fetching of headers
|
||||
tr.eventFilters = make([]common.Hash, 0) // Holds topic0 hashes across all contracts, for batch fetching of logs
|
||||
tr.start = 100000000000 // Hold the lowest starting block and the highest ending block
|
||||
tr.Start = 100000000000
|
||||
|
||||
// Iterate through all internal contract addresses
|
||||
for contractAddr := range tr.Config.Addresses {
|
||||
@@ -120,7 +120,7 @@ func (tr *Transformer) Init() error {
|
||||
}
|
||||
|
||||
// Get first block and most recent block number in the header repo
|
||||
firstBlock, err := tr.BlockRetriever.RetrieveFirstBlock()
|
||||
firstBlock, err := tr.Retriever.RetrieveFirstBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func (tr *Transformer) Init() error {
|
||||
|
||||
// Get contract name if it has one
|
||||
var name = new(string)
|
||||
tr.Poller.FetchContractData(tr.Abi(), contractAddr, "name", nil, name, -1)
|
||||
tr.Poller.FetchContractData(tr.Parser.Abi(), contractAddr, "name", nil, name, -1)
|
||||
|
||||
// Remove any potential accidental duplicate inputs
|
||||
eventArgs := map[string]bool{}
|
||||
@@ -152,7 +152,6 @@ func (tr *Transformer) Init() error {
|
||||
Abi: tr.Parser.Abi(),
|
||||
ParsedAbi: tr.Parser.ParsedAbi(),
|
||||
StartingBlock: firstBlock,
|
||||
LastBlock: -1,
|
||||
Events: tr.Parser.GetEvents(tr.Config.Events[contractAddr]),
|
||||
Methods: tr.Parser.GetSelectMethods(tr.Config.Methods[contractAddr]),
|
||||
FilterArgs: eventArgs,
|
||||
@@ -189,8 +188,8 @@ func (tr *Transformer) Init() error {
|
||||
}
|
||||
|
||||
// Update start to the lowest block
|
||||
if con.StartingBlock < tr.start {
|
||||
tr.start = con.StartingBlock
|
||||
if con.StartingBlock < tr.Start {
|
||||
tr.Start = con.StartingBlock
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,20 +201,20 @@ func (tr *Transformer) Execute() error {
|
||||
return errors.New("error: transformer has no initialized contracts")
|
||||
}
|
||||
|
||||
// Map to sort batch fetched logs by which contract they belong to, for post fetch processing
|
||||
sortedLogs := make(map[string][]gethTypes.Log)
|
||||
for _, con := range tr.Contracts {
|
||||
sortedLogs[con.Address] = []gethTypes.Log{}
|
||||
}
|
||||
|
||||
// Find unchecked headers for all events across all contracts; these are returned in asc order
|
||||
missingHeaders, err := tr.HeaderRepository.MissingHeadersForAll(tr.start, -1, tr.eventIds)
|
||||
missingHeaders, err := tr.HeaderRepository.MissingHeadersForAll(tr.Start, -1, tr.eventIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Iterate over headers
|
||||
for _, header := range missingHeaders {
|
||||
// Set `start` to this header
|
||||
// This way if we throw an error but don't bring the execution cycle down (how it is currently handled)
|
||||
// we restart the cycle at this header
|
||||
tr.Start = header.BlockNumber
|
||||
// Map to sort batch fetched logs by which contract they belong to, for post fetch processing
|
||||
sortedLogs := make(map[string][]gethTypes.Log)
|
||||
// And fetch all event logs across contracts at this header
|
||||
allLogs, err := tr.Fetcher.FetchLogs(tr.contractAddresses, tr.eventFilters, header)
|
||||
if err != nil {
|
||||
@@ -233,6 +232,7 @@ func (tr *Transformer) Execute() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tr.Start = header.BlockNumber + 1 // Empty header; setup to start at the next header
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -249,10 +249,10 @@ func (tr *Transformer) Execute() error {
|
||||
}
|
||||
// Configure converter with this contract
|
||||
con := tr.Contracts[conAddr]
|
||||
tr.ConverterInterface.Update(con)
|
||||
tr.Converter.Update(con)
|
||||
|
||||
// Convert logs into batches of log mappings (eventName => []types.Logs
|
||||
convertedLogs, err := tr.ConverterInterface.ConvertBatch(logs, con.Events, header.Id)
|
||||
convertedLogs, err := tr.Converter.ConvertBatch(logs, con.Events, header.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -281,8 +281,8 @@ func (tr *Transformer) Execute() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tr.start = header.BlockNumber + 1
|
||||
// Success; setup to start at the next header
|
||||
tr.Start = header.BlockNumber + 1
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -19,6 +19,7 @@ package transformer_test
|
||||
import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/light/retriever"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/light/transformer"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/contract"
|
||||
@@ -54,7 +55,47 @@ var _ = Describe("Transformer", func() {
|
||||
Expect(ok).To(Equal(true))
|
||||
|
||||
Expect(c.StartingBlock).To(Equal(firstBlock))
|
||||
Expect(c.LastBlock).To(Equal(int64(-1)))
|
||||
Expect(c.Abi).To(Equal(fakeAbi))
|
||||
Expect(c.Name).To(Equal(fakeContractName))
|
||||
Expect(c.Address).To(Equal(fakeAddress))
|
||||
})
|
||||
|
||||
It("Fails to initialize if first block cannot be fetched from vDB headers table", func() {
|
||||
blockRetriever := &fakes.MockLightBlockRetriever{}
|
||||
blockRetriever.FirstBlockErr = fakes.FakeError
|
||||
t := getFakeTransformer(blockRetriever, &fakes.MockParser{}, &fakes.MockPoller{})
|
||||
|
||||
err := t.Init()
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(fakes.FakeError))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Execute", func() {
|
||||
It("Executes contract transformations", func() {
|
||||
blockRetriever := &fakes.MockLightBlockRetriever{}
|
||||
firstBlock := int64(1)
|
||||
blockRetriever.FirstBlock = firstBlock
|
||||
|
||||
parsr := &fakes.MockParser{}
|
||||
fakeAbi := "fake_abi"
|
||||
parsr.AbiToReturn = fakeAbi
|
||||
|
||||
pollr := &fakes.MockPoller{}
|
||||
fakeContractName := "fake_contract_name"
|
||||
pollr.ContractName = fakeContractName
|
||||
|
||||
t := getFakeTransformer(blockRetriever, parsr, pollr)
|
||||
|
||||
err := t.Init()
|
||||
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
c, ok := t.Contracts[fakeAddress]
|
||||
Expect(ok).To(Equal(true))
|
||||
|
||||
Expect(c.StartingBlock).To(Equal(firstBlock))
|
||||
Expect(c.Abi).To(Equal(fakeAbi))
|
||||
Expect(c.Name).To(Equal(fakeContractName))
|
||||
Expect(c.Address).To(Equal(fakeAddress))
|
||||
@@ -76,7 +117,7 @@ var _ = Describe("Transformer", func() {
|
||||
func getFakeTransformer(blockRetriever retriever.BlockRetriever, parsr parser.Parser, pollr poller.Poller) transformer.Transformer {
|
||||
return transformer.Transformer{
|
||||
Parser: parsr,
|
||||
BlockRetriever: blockRetriever,
|
||||
Retriever: blockRetriever,
|
||||
Poller: pollr,
|
||||
HeaderRepository: &fakes.MockLightHeaderRepository{},
|
||||
Contracts: map[string]*contract.Contract{},
|
||||
|
||||
@@ -34,7 +34,6 @@ type Contract struct {
|
||||
Address string // Address of the contract
|
||||
Network string // Network on which the contract is deployed; default empty "" is Ethereum mainnet
|
||||
StartingBlock int64 // Starting block of the contract
|
||||
LastBlock int64 // Most recent block on the network
|
||||
Abi string // Abi string
|
||||
ParsedAbi abi.ABI // Parsed abi
|
||||
Events map[string]types.Event // List of events to watch
|
||||
|
||||
@@ -168,7 +168,6 @@ func SetupTusdContract(wantedEvents, wantedMethods []string) *contract.Contract
|
||||
Abi: p.Abi(),
|
||||
ParsedAbi: p.ParsedAbi(),
|
||||
StartingBlock: 6194634,
|
||||
LastBlock: 6507323,
|
||||
Events: p.GetEvents(wantedEvents),
|
||||
Methods: p.GetSelectMethods(wantedMethods),
|
||||
MethodArgs: map[string]bool{},
|
||||
@@ -215,7 +214,6 @@ func SetupENSContract(wantedEvents, wantedMethods []string) *contract.Contract {
|
||||
Abi: p.Abi(),
|
||||
ParsedAbi: p.ParsedAbi(),
|
||||
StartingBlock: 6194634,
|
||||
LastBlock: 6507323,
|
||||
Events: p.GetEvents(wantedEvents),
|
||||
Methods: p.GetSelectMethods(wantedMethods),
|
||||
MethodArgs: map[string]bool{},
|
||||
@@ -224,7 +222,7 @@ func SetupENSContract(wantedEvents, wantedMethods []string) *contract.Contract {
|
||||
}
|
||||
|
||||
func TearDown(db *postgres.DB) {
|
||||
tx, err := db.Begin()
|
||||
tx, err := db.Beginx()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = tx.Exec(`DELETE FROM blocks`)
|
||||
|
||||
@@ -98,7 +98,7 @@ func (p *parser) lookUp(contractAddr string) (string, error) {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return "", errors.New("ABI not present in lookup tabe")
|
||||
return "", errors.New("ABI not present in lookup table")
|
||||
}
|
||||
|
||||
// Returns only specified methods, if they meet the criteria
|
||||
|
||||
@@ -34,7 +34,7 @@ import (
|
||||
)
|
||||
|
||||
type Poller interface {
|
||||
PollContract(con contract.Contract) error
|
||||
PollContract(con contract.Contract, lastBlock int64) error
|
||||
PollContractAt(con contract.Contract, blockNumber int64) error
|
||||
FetchContractData(contractAbi, contractAddress, method string, methodArgs []interface{}, result interface{}, blockNumber int64) error
|
||||
}
|
||||
@@ -52,8 +52,8 @@ func NewPoller(blockChain core.BlockChain, db *postgres.DB, mode types.Mode) *po
|
||||
}
|
||||
}
|
||||
|
||||
func (p *poller) PollContract(con contract.Contract) error {
|
||||
for i := con.StartingBlock; i <= con.LastBlock; i++ {
|
||||
func (p *poller) PollContract(con contract.Contract, lastBlock int64) error {
|
||||
for i := con.StartingBlock; i <= lastBlock; i++ {
|
||||
if err := p.PollContractAt(con, i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// VulcanizeDB
|
||||
// Copyright © 2019 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 poller_test
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestPoller(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Poller Suite Test")
|
||||
}
|
||||
|
||||
var _ = BeforeSuite(func() {
|
||||
logrus.SetOutput(ioutil.Discard)
|
||||
})
|
||||
@@ -1,257 +0,0 @@
|
||||
// VulcanizeDB
|
||||
// Copyright © 2019 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 poller_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/constants"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/contract"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/helpers/test_helpers"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/poller"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/contract_watcher/shared/types"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
|
||||
)
|
||||
|
||||
var _ = Describe("Poller", func() {
|
||||
|
||||
var p poller.Poller
|
||||
var con *contract.Contract
|
||||
var db *postgres.DB
|
||||
var bc core.BlockChain
|
||||
|
||||
AfterEach(func() {
|
||||
test_helpers.TearDown(db)
|
||||
})
|
||||
|
||||
Describe("Full sync mode", func() {
|
||||
BeforeEach(func() {
|
||||
db, bc = test_helpers.SetupDBandBC()
|
||||
p = poller.NewPoller(bc, db, types.FullSync)
|
||||
})
|
||||
|
||||
Describe("PollContract", func() {
|
||||
It("Polls specified contract methods using contract's argument list", func() {
|
||||
con = test_helpers.SetupTusdContract(nil, []string{"balanceOf"})
|
||||
Expect(con.Abi).To(Equal(constants.TusdAbiString))
|
||||
con.StartingBlock = 6707322
|
||||
con.LastBlock = 6707323
|
||||
con.AddEmittedAddr(common.HexToAddress("0xfE9e8709d3215310075d67E3ed32A380CCf451C8"), common.HexToAddress("0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE"))
|
||||
|
||||
err := p.PollContract(*con)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
scanStruct := test_helpers.BalanceOf{}
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.balanceof_method WHERE who_ = '0xfE9e8709d3215310075d67E3ed32A380CCf451C8' AND block = '6707322'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("66386309548896882859581786"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.balanceof_method WHERE who_ = '0xfE9e8709d3215310075d67E3ed32A380CCf451C8' AND block = '6707323'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("66386309548896882859581786"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.balanceof_method WHERE who_ = '0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE' AND block = '6707322'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("17982350181394112023885864"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.balanceof_method WHERE who_ = '0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE' AND block = '6707323'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("17982350181394112023885864"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
})
|
||||
|
||||
It("Polls specified contract methods using contract's hash list", func() {
|
||||
con = test_helpers.SetupENSContract(nil, []string{"owner"})
|
||||
Expect(con.Abi).To(Equal(constants.ENSAbiString))
|
||||
Expect(len(con.Methods)).To(Equal(1))
|
||||
con.AddEmittedHash(common.HexToHash("0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae"), common.HexToHash("0x7e74a86b6e146964fb965db04dc2590516da77f720bb6759337bf5632415fd86"))
|
||||
|
||||
err := p.PollContractAt(*con, 6885877)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
scanStruct := test_helpers.Owner{}
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.owner_method WHERE node_ = '0x7e74a86b6e146964fb965db04dc2590516da77f720bb6759337bf5632415fd86' AND block = '6885877'", constants.EnsContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Address).To(Equal("0x546aA2EaE2514494EeaDb7bbb35243348983C59d"))
|
||||
Expect(scanStruct.TokenName).To(Equal("ENS-Registry"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.owner_method WHERE node_ = '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae' AND block = '6885877'", constants.EnsContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Address).To(Equal("0x6090A6e47849629b7245Dfa1Ca21D94cd15878Ef"))
|
||||
Expect(scanStruct.TokenName).To(Equal("ENS-Registry"))
|
||||
})
|
||||
|
||||
It("Does not poll and persist any methods if none are specified", func() {
|
||||
con = test_helpers.SetupTusdContract(nil, nil)
|
||||
Expect(con.Abi).To(Equal(constants.TusdAbiString))
|
||||
con.StartingBlock = 6707322
|
||||
con.LastBlock = 6707323
|
||||
con.AddEmittedAddr(common.HexToAddress("0xfE9e8709d3215310075d67E3ed32A380CCf451C8"), common.HexToAddress("0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE"))
|
||||
|
||||
err := p.PollContract(*con)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
scanStruct := test_helpers.BalanceOf{}
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM full_%s.balanceof_method WHERE who_ = '0xfE9e8709d3215310075d67E3ed32A380CCf451C8' AND block = '6707322'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("FetchContractData", func() {
|
||||
It("Calls a single contract method", func() {
|
||||
var name = new(string)
|
||||
err := p.FetchContractData(constants.TusdAbiString, constants.TusdContractAddress, "name", nil, &name, 6197514)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(*name).To(Equal("TrueUSD"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Light sync mode", func() {
|
||||
BeforeEach(func() {
|
||||
db, bc = test_helpers.SetupDBandBC()
|
||||
p = poller.NewPoller(bc, db, types.LightSync)
|
||||
})
|
||||
|
||||
Describe("PollContract", func() {
|
||||
It("Polls specified contract methods using contract's token holder address list", func() {
|
||||
con = test_helpers.SetupTusdContract(nil, []string{"balanceOf"})
|
||||
Expect(con.Abi).To(Equal(constants.TusdAbiString))
|
||||
con.StartingBlock = 6707322
|
||||
con.LastBlock = 6707323
|
||||
con.AddEmittedAddr(common.HexToAddress("0xfE9e8709d3215310075d67E3ed32A380CCf451C8"), common.HexToAddress("0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE"))
|
||||
|
||||
err := p.PollContract(*con)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
scanStruct := test_helpers.BalanceOf{}
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.balanceof_method WHERE who_ = '0xfE9e8709d3215310075d67E3ed32A380CCf451C8' AND block = '6707322'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("66386309548896882859581786"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.balanceof_method WHERE who_ = '0xfE9e8709d3215310075d67E3ed32A380CCf451C8' AND block = '6707323'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("66386309548896882859581786"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.balanceof_method WHERE who_ = '0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE' AND block = '6707322'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("17982350181394112023885864"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.balanceof_method WHERE who_ = '0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE' AND block = '6707323'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Balance).To(Equal("17982350181394112023885864"))
|
||||
Expect(scanStruct.TokenName).To(Equal("TrueUSD"))
|
||||
})
|
||||
|
||||
It("Polls specified contract methods using contract's hash list", func() {
|
||||
con = test_helpers.SetupENSContract(nil, []string{"owner"})
|
||||
Expect(con.Abi).To(Equal(constants.ENSAbiString))
|
||||
Expect(len(con.Methods)).To(Equal(1))
|
||||
con.AddEmittedHash(common.HexToHash("0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae"), common.HexToHash("0x7e74a86b6e146964fb965db04dc2590516da77f720bb6759337bf5632415fd86"))
|
||||
|
||||
err := p.PollContractAt(*con, 6885877)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
scanStruct := test_helpers.Owner{}
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.owner_method WHERE node_ = '0x7e74a86b6e146964fb965db04dc2590516da77f720bb6759337bf5632415fd86' AND block = '6885877'", constants.EnsContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Address).To(Equal("0x546aA2EaE2514494EeaDb7bbb35243348983C59d"))
|
||||
Expect(scanStruct.TokenName).To(Equal("ENS-Registry"))
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.owner_method WHERE node_ = '0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae' AND block = '6885877'", constants.EnsContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Address).To(Equal("0x6090A6e47849629b7245Dfa1Ca21D94cd15878Ef"))
|
||||
Expect(scanStruct.TokenName).To(Equal("ENS-Registry"))
|
||||
})
|
||||
|
||||
It("Does not poll and persist any methods if none are specified", func() {
|
||||
con = test_helpers.SetupTusdContract(nil, nil)
|
||||
Expect(con.Abi).To(Equal(constants.TusdAbiString))
|
||||
con.StartingBlock = 6707322
|
||||
con.LastBlock = 6707323
|
||||
con.AddEmittedAddr(common.HexToAddress("0xfE9e8709d3215310075d67E3ed32A380CCf451C8"), common.HexToAddress("0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE"))
|
||||
|
||||
err := p.PollContract(*con)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
scanStruct := test_helpers.BalanceOf{}
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.balanceof_method WHERE who_ = '0xfE9e8709d3215310075d67E3ed32A380CCf451C8' AND block = '6707322'", constants.TusdContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
|
||||
It("Caches returned values of the appropriate types for downstream method polling if method piping is turned on", func() {
|
||||
con = test_helpers.SetupENSContract(nil, []string{"resolver"})
|
||||
Expect(con.Abi).To(Equal(constants.ENSAbiString))
|
||||
con.StartingBlock = 6921967
|
||||
con.LastBlock = 6921968
|
||||
con.EmittedAddrs = map[interface{}]bool{}
|
||||
con.Piping = false
|
||||
con.AddEmittedHash(common.HexToHash("0x495b6e6efdedb750aa519919b5cf282bdaa86067b82a2293a3ff5723527141e8"))
|
||||
err := p.PollContract(*con)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
scanStruct := test_helpers.Resolver{}
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.resolver_method WHERE node_ = '0x495b6e6efdedb750aa519919b5cf282bdaa86067b82a2293a3ff5723527141e8' AND block = '6921967'", constants.EnsContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Address).To(Equal("0x5FfC014343cd971B7eb70732021E26C35B744cc4"))
|
||||
Expect(scanStruct.TokenName).To(Equal("ENS-Registry"))
|
||||
Expect(len(con.EmittedAddrs)).To(Equal(0)) // With piping off the address is not saved
|
||||
|
||||
test_helpers.TearDown(db)
|
||||
db, bc = test_helpers.SetupDBandBC()
|
||||
p = poller.NewPoller(bc, db, types.LightSync)
|
||||
|
||||
con.Piping = true
|
||||
err = p.PollContract(*con)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = db.QueryRowx(fmt.Sprintf("SELECT * FROM light_%s.resolver_method WHERE node_ = '0x495b6e6efdedb750aa519919b5cf282bdaa86067b82a2293a3ff5723527141e8' AND block = '6921967'", constants.EnsContractAddress)).StructScan(&scanStruct)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(scanStruct.Address).To(Equal("0x5FfC014343cd971B7eb70732021E26C35B744cc4"))
|
||||
Expect(scanStruct.TokenName).To(Equal("ENS-Registry"))
|
||||
Expect(len(con.EmittedAddrs)).To(Equal(1)) // With piping on it is saved
|
||||
Expect(con.EmittedAddrs[common.HexToAddress("0x5FfC014343cd971B7eb70732021E26C35B744cc4")]).To(Equal(true))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("FetchContractData", func() {
|
||||
It("Calls a single contract method", func() {
|
||||
var name = new(string)
|
||||
err := p.FetchContractData(constants.TusdAbiString, constants.TusdContractAddress, "name", nil, &name, 6197514)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(*name).To(Equal("TrueUSD"))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -97,7 +97,7 @@ func (r *eventRepository) persistLogs(logs []types.Log, eventInfo types.Event, c
|
||||
|
||||
// Creates a custom postgres command to persist logs for the given event (compatible with light synced vDB)
|
||||
func (r *eventRepository) persistLightSyncLogs(logs []types.Log, eventInfo types.Event, contractAddr, contractName string) error {
|
||||
tx, err := r.db.Begin()
|
||||
tx, err := r.db.Beginx()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -151,7 +151,7 @@ func (r *eventRepository) persistLightSyncLogs(logs []types.Log, eventInfo types
|
||||
|
||||
// Creates a custom postgres command to persist logs for the given event (compatible with fully synced vDB)
|
||||
func (r *eventRepository) persistFullSyncLogs(logs []types.Log, eventInfo types.Event, contractAddr, contractName string) error {
|
||||
tx, err := r.db.Begin()
|
||||
tx, err := r.db.Beginx()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ func (r *methodRepository) PersistResults(results []types.Result, methodInfo typ
|
||||
|
||||
// Creates a custom postgres command to persist logs for the given event
|
||||
func (r *methodRepository) persistResults(results []types.Result, methodInfo types.Method, contractAddr, contractName string) error {
|
||||
tx, err := r.DB.Begin()
|
||||
tx, err := r.DB.Beginx()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ type MockPoller struct {
|
||||
ContractName string
|
||||
}
|
||||
|
||||
func (*MockPoller) PollContract(con contract.Contract) error {
|
||||
func (*MockPoller) PollContract(con contract.Contract, lastBlock int64) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ func SetupDBandBC() (*postgres.DB, core.BlockChain) {
|
||||
}
|
||||
|
||||
func TearDown(db *postgres.DB) {
|
||||
tx, err := db.Begin()
|
||||
tx, err := db.Beginx()
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = tx.Exec(`DELETE FROM headers`)
|
||||
|
||||
Reference in New Issue
Block a user