From 981393d0a7b54c1a70d6c86eebfa7519a7680768 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Fri, 2 Nov 2018 09:12:51 -0500 Subject: [PATCH] Use transformer factory for FlipKick (#96) --- pkg/transformers/flip_kick/config.go | 5 +- pkg/transformers/flip_kick/converter.go | 49 ++++--- pkg/transformers/flip_kick/converter_test.go | 15 +- .../flip_kick/integration_test.go | 52 ------- pkg/transformers/flip_kick/repository.go | 33 +++-- pkg/transformers/flip_kick/repository_test.go | 31 +++-- pkg/transformers/flip_kick/transformer.go | 131 ------------------ .../flip_kick/transformer_test.go | 109 +++++++-------- .../integration_tests/flip_kick.go | 38 ++++- .../test_data/mocks/flip_kick/converter.go | 48 ------- .../test_data/mocks/flip_kick/repository.go | 73 ---------- pkg/transformers/transformers.go | 10 +- 12 files changed, 173 insertions(+), 421 deletions(-) delete mode 100644 pkg/transformers/flip_kick/integration_test.go delete mode 100644 pkg/transformers/flip_kick/transformer.go delete mode 100644 pkg/transformers/test_data/mocks/flip_kick/converter.go delete mode 100644 pkg/transformers/test_data/mocks/flip_kick/repository.go diff --git a/pkg/transformers/flip_kick/config.go b/pkg/transformers/flip_kick/config.go index 98fe2074..b9ba11b8 100644 --- a/pkg/transformers/flip_kick/config.go +++ b/pkg/transformers/flip_kick/config.go @@ -16,10 +16,11 @@ package flip_kick import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -var FlipKickConfig = shared.TransformerConfig{ +var FlipKickConfig = shared.SingleTransformerConfig{ + TransformerName: shared.FlipKickLabel, ContractAddresses: []string{shared.FlipperContractAddress}, ContractAbi: shared.FlipperABI, - Topics: []string{shared.FlipKickSignature}, + Topic: shared.FlipKickSignature, StartingBlockNumber: 0, EndingBlockNumber: 10000000, } diff --git a/pkg/transformers/flip_kick/converter.go b/pkg/transformers/flip_kick/converter.go index 3f749704..0702c868 100644 --- a/pkg/transformers/flip_kick/converter.go +++ b/pkg/transformers/flip_kick/converter.go @@ -23,18 +23,15 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "fmt" "github.com/vulcanize/vulcanizedb/pkg/geth" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) -type Converter interface { - ToEntities(contractAbi string, ethLogs []types.Log) ([]FlipKickEntity, error) - ToModels(flipKicks []FlipKickEntity) ([]FlipKickModel, error) -} - type FlipKickConverter struct{} -func (FlipKickConverter) ToEntities(contractAbi string, ethLogs []types.Log) (results []FlipKickEntity, err error) { +func (FlipKickConverter) ToEntities(contractAbi string, ethLogs []types.Log) ([]interface{}, error) { + var entities []interface{} for _, ethLog := range ethLogs { entity := &FlipKickEntity{} address := ethLog.Address @@ -52,27 +49,33 @@ func (FlipKickConverter) ToEntities(contractAbi string, ethLogs []types.Log) (re entity.Raw = ethLog entity.TransactionIndex = ethLog.TxIndex entity.LogIndex = ethLog.Index - results = append(results, *entity) + entities = append(entities, *entity) } - return results, nil + return entities, nil } -func (FlipKickConverter) ToModels(flipKicks []FlipKickEntity) (results []FlipKickModel, err error) { - for _, flipKick := range flipKicks { - if flipKick.Id == nil { +func (FlipKickConverter) ToModels(entities []interface{}) ([]interface{}, error) { + var models []interface{} + for _, entity := range entities { + flipKickEntity, ok := entity.(FlipKickEntity) + if !ok { + return nil, fmt.Errorf("entity of type %T, not %T", entity, FlipKickEntity{}) + } + + if flipKickEntity.Id == nil { return nil, errors.New("FlipKick log ID cannot be nil.") } - id := flipKick.Id.String() - lot := shared.BigIntToString(flipKick.Lot) - bid := shared.BigIntToString(flipKick.Bid) - gal := flipKick.Gal.String() - endValue := shared.BigIntToInt64(flipKick.End) + id := flipKickEntity.Id.String() + lot := shared.BigIntToString(flipKickEntity.Lot) + bid := shared.BigIntToString(flipKickEntity.Bid) + gal := flipKickEntity.Gal.String() + endValue := shared.BigIntToInt64(flipKickEntity.End) end := time.Unix(endValue, 0) - urn := common.BytesToAddress(flipKick.Urn[:common.AddressLength]).String() - tab := shared.BigIntToString(flipKick.Tab) - rawLogJson, err := json.Marshal(flipKick.Raw) + urn := common.BytesToAddress(flipKickEntity.Urn[:common.AddressLength]).String() + tab := shared.BigIntToString(flipKickEntity.Tab) + rawLogJson, err := json.Marshal(flipKickEntity.Raw) if err != nil { return nil, err } @@ -86,11 +89,11 @@ func (FlipKickConverter) ToModels(flipKicks []FlipKickEntity) (results []FlipKic End: end, Urn: urn, Tab: tab, - TransactionIndex: flipKick.TransactionIndex, - LogIndex: flipKick.LogIndex, + TransactionIndex: flipKickEntity.TransactionIndex, + LogIndex: flipKickEntity.LogIndex, Raw: rawLogString, } - results = append(results, model) + models = append(models, model) } - return results, err + return models, nil } diff --git a/pkg/transformers/flip_kick/converter_test.go b/pkg/transformers/flip_kick/converter_test.go index 229d638b..7666d290 100644 --- a/pkg/transformers/flip_kick/converter_test.go +++ b/pkg/transformers/flip_kick/converter_test.go @@ -66,7 +66,7 @@ var _ = Describe("FlipKick Converter", func() { }) It("converts an Entity to a Model", func() { - models, err := converter.ToModels([]flip_kick.FlipKickEntity{test_data.FlipKickEntity}) + models, err := converter.ToModels([]interface{}{test_data.FlipKickEntity}) Expect(err).NotTo(HaveOccurred()) Expect(len(models)).To(Equal(1)) @@ -74,11 +74,11 @@ var _ = Describe("FlipKick Converter", func() { }) It("handles nil values", func() { - models, err := converter.ToModels([]flip_kick.FlipKickEntity{emptyEntity}) + models, err := converter.ToModels([]interface{}{emptyEntity}) Expect(err).NotTo(HaveOccurred()) Expect(len(models)).To(Equal(1)) - model := models[0] + model := models[0].(flip_kick.FlipKickModel) Expect(model.BidId).To(Equal("1")) Expect(model.Lot).To(Equal(emptyString)) Expect(model.Bid).To(Equal(emptyString)) @@ -91,9 +91,16 @@ var _ = Describe("FlipKick Converter", func() { It("returns an error if the flip kick event id is nil", func() { emptyEntity.Id = nil - _, err := converter.ToModels([]flip_kick.FlipKickEntity{emptyEntity}) + _, err := converter.ToModels([]interface{}{emptyEntity}) Expect(err).To(HaveOccurred()) }) + + It("returns an error if the wrong entity type is passed in", func() { + _, err := converter.ToModels([]interface{}{test_data.WrongEntity{}}) + + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("entity of type")) + }) }) }) diff --git a/pkg/transformers/flip_kick/integration_test.go b/pkg/transformers/flip_kick/integration_test.go deleted file mode 100644 index e5141d12..00000000 --- a/pkg/transformers/flip_kick/integration_test.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2018 Vulcanize -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package flip_kick_test - -import ( - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/vulcanize/vulcanizedb/pkg/geth" - "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" - "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" -) - -var _ = Describe("Integration tests", func() { - It("unpacks an event log", func() { - address := common.HexToAddress(shared.FlipperContractAddress) - abi, err := geth.ParseAbi(shared.FlipperABI) - Expect(err).NotTo(HaveOccurred()) - - contract := bind.NewBoundContract(address, abi, nil, nil, nil) - entity := &flip_kick.FlipKickEntity{} - - var eventLog = test_data.EthFlipKickLog - - err = contract.UnpackLog(entity, "Kick", eventLog) - Expect(err).NotTo(HaveOccurred()) - - expectedEntity := test_data.FlipKickEntity - Expect(entity.Id).To(Equal(expectedEntity.Id)) - Expect(entity.Lot).To(Equal(expectedEntity.Lot)) - Expect(entity.Bid).To(Equal(expectedEntity.Bid)) - Expect(entity.Gal).To(Equal(expectedEntity.Gal)) - Expect(entity.End).To(Equal(expectedEntity.End)) - Expect(entity.Urn).To(Equal(expectedEntity.Urn)) - Expect(entity.Tab).To(Equal(expectedEntity.Tab)) - }) -}) diff --git a/pkg/transformers/flip_kick/repository.go b/pkg/transformers/flip_kick/repository.go index 855c865b..5e03f48e 100644 --- a/pkg/transformers/flip_kick/repository.go +++ b/pkg/transformers/flip_kick/repository.go @@ -21,29 +21,24 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerId int64, flipKicks []FlipKickModel) error - MarkHeaderChecked(headerId int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type FlipKickRepository struct { - DB *postgres.DB + db *postgres.DB } -func NewFlipKickRepository(db *postgres.DB) FlipKickRepository { - return FlipKickRepository{DB: db} -} -func (fkr FlipKickRepository) Create(headerId int64, flipKicks []FlipKickModel) error { - tx, err := fkr.DB.Begin() +func (fkr FlipKickRepository) Create(headerId int64, models []interface{}) error { + tx, err := fkr.db.Begin() if err != nil { return err } - for _, flipKick := range flipKicks { + for _, model := range models { + flipKickModel, ok := model.(FlipKickModel) + if !ok { + return fmt.Errorf("model of type %T, not %T", model, FlipKickModel{}) + } _, err := tx.Exec( `INSERT into maker.flip_kick (header_id, bid_id, lot, bid, gal, "end", urn, tab, tx_idx, log_idx, raw_log) VALUES($1, $2::NUMERIC, $3::NUMERIC, $4::NUMERIC, $5, $6, $7, $8::NUMERIC, $9, $10, $11)`, - headerId, flipKick.BidId, flipKick.Lot, flipKick.Bid, flipKick.Gal, flipKick.End, flipKick.Urn, flipKick.Tab, flipKick.TransactionIndex, flipKick.LogIndex, flipKick.Raw, + headerId, flipKickModel.BidId, flipKickModel.Lot, flipKickModel.Bid, flipKickModel.Gal, flipKickModel.End, flipKickModel.Urn, flipKickModel.Tab, flipKickModel.TransactionIndex, flipKickModel.LogIndex, flipKickModel.Raw, ) if err != nil { tx.Rollback() @@ -62,7 +57,7 @@ func (fkr FlipKickRepository) Create(headerId int64, flipKicks []FlipKickModel) } func (fkr FlipKickRepository) MarkHeaderChecked(headerId int64) error { - _, err := fkr.DB.Exec(`INSERT INTO public.checked_headers (header_id, flip_kick_checked) + _, err := fkr.db.Exec(`INSERT INTO public.checked_headers (header_id, flip_kick_checked) VALUES ($1, $2) ON CONFLICT (header_id) DO UPDATE SET flip_kick_checked = $2`, headerId, true) @@ -71,7 +66,7 @@ func (fkr FlipKickRepository) MarkHeaderChecked(headerId int64) error { func (fkr FlipKickRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { var result []core.Header - err := fkr.DB.Select( + err := fkr.db.Select( &result, `SELECT headers.id, headers.block_number FROM headers LEFT JOIN checked_headers on headers.id = header_id @@ -81,7 +76,7 @@ func (fkr FlipKickRepository) MissingHeaders(startingBlockNumber, endingBlockNum AND headers.eth_node_fingerprint = $3`, startingBlockNumber, endingBlockNumber, - fkr.DB.Node.ID, + fkr.db.Node.ID, ) if err != nil { @@ -91,3 +86,7 @@ func (fkr FlipKickRepository) MissingHeaders(startingBlockNumber, endingBlockNum return result, nil } + +func (fkr *FlipKickRepository) SetDB(db *postgres.DB) { + fkr.db = db +} diff --git a/pkg/transformers/flip_kick/repository_test.go b/pkg/transformers/flip_kick/repository_test.go index f88b9bbd..509f1a0a 100644 --- a/pkg/transformers/flip_kick/repository_test.go +++ b/pkg/transformers/flip_kick/repository_test.go @@ -37,7 +37,8 @@ var _ = Describe("FlipKick Repository", func() { BeforeEach(func() { db = test_config.NewTestDB(test_config.NewTestNode()) test_config.CleanTestDB(db) - flipKickRepository = flip_kick.FlipKickRepository{DB: db} + flipKickRepository = flip_kick.FlipKickRepository{} + flipKickRepository.SetDB(db) blockNumber = GinkgoRandomSeed() headerId = createHeader(db, blockNumber) @@ -47,18 +48,18 @@ var _ = Describe("FlipKick Repository", func() { Describe("Create", func() { AfterEach(func() { - _, err := db.Exec(`DELETE from headers;`) + _, err := db.Exec(`DELETE from headers`) Expect(err).NotTo(HaveOccurred()) }) It("persists flip_kick records", func() { - err := flipKickRepository.Create(headerId, []flip_kick.FlipKickModel{flipKick}) + err := flipKickRepository.Create(headerId, []interface{}{flipKick}) Expect(err).NotTo(HaveOccurred()) assertDBRecordCount(db, "maker.flip_kick", 1) dbResult := test_data.FlipKickDBRow{} - err = flipKickRepository.DB.QueryRowx(`SELECT * FROM maker.flip_kick`).StructScan(&dbResult) + err = db.QueryRowx(`SELECT * FROM maker.flip_kick`).StructScan(&dbResult) Expect(err).NotTo(HaveOccurred()) Expect(dbResult.HeaderId).To(Equal(headerId)) Expect(dbResult.BidId).To(Equal(flipKick.BidId)) @@ -74,7 +75,7 @@ var _ = Describe("FlipKick Repository", func() { }) It("marks header checked", func() { - err := flipKickRepository.Create(headerId, []flip_kick.FlipKickModel{flipKick}) + err := flipKickRepository.Create(headerId, []interface{}{flipKick}) Expect(err).NotTo(HaveOccurred()) var headerChecked bool @@ -86,7 +87,7 @@ var _ = Describe("FlipKick Repository", func() { It("updates the header to checked if checked headers row already exists", func() { _, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerId) Expect(err).NotTo(HaveOccurred()) - err = flipKickRepository.Create(headerId, []flip_kick.FlipKickModel{flipKick}) + err = flipKickRepository.Create(headerId, []interface{}{flipKick}) Expect(err).NotTo(HaveOccurred()) var headerChecked bool @@ -96,10 +97,10 @@ var _ = Describe("FlipKick Repository", func() { }) It("returns an error if inserting the flip_kick record fails", func() { - err := flipKickRepository.Create(headerId, []flip_kick.FlipKickModel{flipKick}) + err := flipKickRepository.Create(headerId, []interface{}{flipKick}) Expect(err).NotTo(HaveOccurred()) - err = flipKickRepository.Create(headerId, []flip_kick.FlipKickModel{flipKick}) + err = flipKickRepository.Create(headerId, []interface{}{flipKick}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) }) @@ -107,13 +108,13 @@ var _ = Describe("FlipKick Repository", func() { It("allows for multiple flip kick events in one transaction if they have different log indexes", func() { newFlipKick := test_data.FlipKickModel newFlipKick.LogIndex = newFlipKick.LogIndex + 1 - err := flipKickRepository.Create(headerId, []flip_kick.FlipKickModel{newFlipKick}) + err := flipKickRepository.Create(headerId, []interface{}{newFlipKick}) Expect(err).NotTo(HaveOccurred()) }) It("deletes the flip_kick records if its corresponding header record is deleted", func() { - err := flipKickRepository.Create(headerId, []flip_kick.FlipKickModel{flipKick}) + err := flipKickRepository.Create(headerId, []interface{}{flipKick}) Expect(err).NotTo(HaveOccurred()) assertDBRecordCount(db, "maker.flip_kick", 1) assertDBRecordCount(db, "headers", 1) @@ -124,6 +125,13 @@ var _ = Describe("FlipKick Repository", func() { assertDBRecordCount(db, "headers", 0) assertDBRecordCount(db, "maker.flip_kick", 0) }) + + It("returns an error if the wrong model type is passed in", func() { + err := flipKickRepository.Create(headerId, []interface{}{test_data.WrongModel{}}) + + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -164,7 +172,8 @@ var _ = Describe("FlipKick Repository", func() { ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9", } db2 = test_config.NewTestDB(node2) - flipKickRepository2 = flip_kick.FlipKickRepository{DB: db2} + flipKickRepository2 = flip_kick.FlipKickRepository{} + flipKickRepository2.SetDB(db2) createHeader(db2, blockNumber) _, err := db2.Exec(`DELETE from maker.flip_kick;`) diff --git a/pkg/transformers/flip_kick/transformer.go b/pkg/transformers/flip_kick/transformer.go deleted file mode 100644 index 507b6497..00000000 --- a/pkg/transformers/flip_kick/transformer.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2018 Vulcanize -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package flip_kick - -import ( - "errors" - "fmt" - "log" - - "github.com/ethereum/go-ethereum/common" - - "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -) - -type FlipKickTransformer struct { - Fetcher shared.LogFetcher - Converter Converter - Repository Repository - Config shared.TransformerConfig -} - -type FlipKickTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (i FlipKickTransformerInitializer) NewFlipKickTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - fetcher := shared.NewFetcher(blockChain) - repository := NewFlipKickRepository(db) - transformer := FlipKickTransformer{ - Fetcher: fetcher, - Repository: repository, - Converter: FlipKickConverter{}, - Config: i.Config, - } - - return transformer -} - -func (fkt *FlipKickTransformer) SetConfig(config shared.TransformerConfig) { - fkt.Config = config -} - -const ( - FetcherError = "Error fetching FlipKick log events for block number %d: %s" - LogToEntityError = "Error converting eth log to FlipKick entity for block number %d: %s" - EntityToModelError = "Error converting eth log to FlipKick entity for block number %d: %s" - RepositoryError = "Error creating flip_kick record for block number %d: %s" - TransformerError = "There has been %d error(s) transforming FlipKick event logs, see the logs for more details." -) - -type transformerError struct { - err string - blockNumber int64 - msg string -} - -func (te *transformerError) Error() string { - return fmt.Sprintf(te.msg, te.blockNumber, te.err) -} - -func newTransformerError(err error, blockNumber int64, msg string) error { - e := transformerError{err.Error(), blockNumber, msg} - log.Println(e.Error()) - return &e -} - -func (fkt FlipKickTransformer) Execute() error { - config := fkt.Config - topics := [][]common.Hash{{common.HexToHash(shared.FlipKickSignature)}} - - headers, err := fkt.Repository.MissingHeaders(config.StartingBlockNumber, config.EndingBlockNumber) - if err != nil { - log.Println("Error:", err) - return err - } - - log.Printf("Fetching flip kick event logs for %d headers \n", len(headers)) - var resultingErrors []error - for _, header := range headers { - ethLogs, err := fkt.Fetcher.FetchLogs(config.ContractAddresses, topics, header.BlockNumber) - if err != nil { - resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, FetcherError)) - } - - if len(ethLogs) < 1 { - err := fkt.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - - entities, err := fkt.Converter.ToEntities(config.ContractAbi, ethLogs) - if err != nil { - resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, LogToEntityError)) - } - models, err := fkt.Converter.ToModels(entities) - if err != nil { - resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, EntityToModelError)) - } - - err = fkt.Repository.Create(header.Id, models) - if err != nil { - resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, RepositoryError)) - } - } - - if len(resultingErrors) > 0 { - for _, err := range resultingErrors { - log.Println(err) - } - - msg := fmt.Sprintf(TransformerError, len(resultingErrors)) - return errors.New(msg) - } - - return nil -} diff --git a/pkg/transformers/flip_kick/transformer_test.go b/pkg/transformers/flip_kick/transformer_test.go index e3ac8c22..de1586a0 100644 --- a/pkg/transformers/flip_kick/transformer_test.go +++ b/pkg/transformers/flip_kick/transformer_test.go @@ -15,59 +15,57 @@ package flip_kick_test import ( - "math/rand" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" - flip_kick_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/flip_kick" + "math/rand" ) var _ = Describe("FlipKick Transformer", func() { - var transformer flip_kick.FlipKickTransformer - var fetcher mocks.MockLogFetcher - var converter flip_kick_mocks.MockFlipKickConverter - var repository flip_kick_mocks.MockFlipKickRepository - var blockNumber int64 - var headerId int64 - var headers []core.Header - var logs []types.Log + var ( + transformer shared.Transformer + fetcher mocks.MockLogFetcher + converter mocks.MockConverter + repository mocks.MockRepository + blockNumber int64 + headerId int64 + headers []core.Header + logs []types.Log + config = flip_kick.FlipKickConfig + ) BeforeEach(func() { fetcher = mocks.MockLogFetcher{} - converter = flip_kick_mocks.MockFlipKickConverter{} - repository = flip_kick_mocks.MockFlipKickRepository{} - transformer = flip_kick.FlipKickTransformer{ + converter = mocks.MockConverter{} + repository = mocks.MockRepository{} + transformer = factories.Transformer{ Fetcher: &fetcher, Converter: &converter, Repository: &repository, + Config: config, } - transformer.SetConfig(flip_kick.FlipKickConfig) blockNumber = rand.Int63() headerId = rand.Int63() + logs = []types.Log{test_data.EthFlipKickLog} headers = []core.Header{{ Id: headerId, BlockNumber: blockNumber, Hash: "0x", Raw: nil, }} - - repository.SetHeadersToReturn(headers) - - logs = []types.Log{test_data.EthFlipKickLog} - fetcher.SetFetchedLogs(logs) }) It("fetches logs with the configured contract and topic(s) for each block", func() { + repository.SetMissingHeaders(headers) expectedTopics := [][]common.Hash{{common.HexToHash(shared.FlipKickSignature)}} err := transformer.Execute() @@ -79,42 +77,26 @@ var _ = Describe("FlipKick Transformer", func() { }) It("returns an error if the fetcher fails", func() { + repository.SetMissingHeaders(headers) fetcher.SetFetcherError(fakes.FakeError) err := transformer.Execute() Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("error(s) transforming FlipKick event logs")) + Expect(err.Error()).To(ContainSubstring("failed")) }) It("marks header checked if no logs returned", func() { - mockConverter := &flip_kick_mocks.MockFlipKickConverter{} - mockRepository := &flip_kick_mocks.MockFlipKickRepository{} - headerID := int64(123) - mockRepository.SetHeadersToReturn([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := flip_kick.FlipKickTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{{Id: headerId}}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerId) }) It("returns error if marking header checked returns err", func() { - mockConverter := &flip_kick_mocks.MockFlipKickConverter{} - mockRepository := &flip_kick_mocks.MockFlipKickRepository{} - mockRepository.SetHeadersToReturn([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := flip_kick.FlipKickTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{{Id: headerId}}) + repository.SetMarkHeaderCheckedError(fakes.FakeError) err := transformer.Execute() @@ -123,49 +105,64 @@ var _ = Describe("FlipKick Transformer", func() { }) It("converts the logs", func() { - err := transformer.Execute() - Expect(err).NotTo(HaveOccurred()) + repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) + fetcher.SetFetchedLogs(logs) - Expect(converter.ConverterContracts).To(Equal(flip_kick.FlipKickConfig.ContractAddresses)) - Expect(converter.ConverterAbi).To(Equal(flip_kick.FlipKickConfig.ContractAbi)) + err := transformer.Execute() + + Expect(err).NotTo(HaveOccurred()) + Expect(converter.ContractAbi).To(Equal(flip_kick.FlipKickConfig.ContractAbi)) Expect(converter.LogsToConvert).To(Equal(logs)) - Expect(converter.EntitiesToConvert).To(Equal([]flip_kick.FlipKickEntity{test_data.FlipKickEntity})) }) It("returns an error if converting the geth log fails", func() { - converter.SetConverterError(fakes.FakeError) + repository.SetMissingHeaders(headers) + fetcher.SetFetchedLogs(logs) + converter.ToEntitiesError = fakes.FakeError err := transformer.Execute() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("failed")) }) It("persists a flip_kick record", func() { - err := transformer.Execute() - Expect(err).NotTo(HaveOccurred()) + repository.SetMissingHeaders(headers) + fetcher.SetFetchedLogs(logs) + converter.ModelsToReturn = []interface{}{test_data.FlipKickModel} - Expect(repository.HeaderIds).To(Equal([]int64{headerId})) - Expect(repository.FlipKicksCreated).To(Equal([]flip_kick.FlipKickModel{test_data.FlipKickModel})) + err := transformer.Execute() + + Expect(err).NotTo(HaveOccurred()) + Expect(repository.PassedHeaderID).To(Equal(headerId)) + Expect(repository.PassedModels[0]).To(Equal(test_data.FlipKickModel)) }) It("returns an error if persisting a record fails", func() { - repository.SetCreateRecordError(fakes.FakeError) + repository.SetCreateError(fakes.FakeError) + repository.SetMissingHeaders(headers) + fetcher.SetFetchedLogs(logs) err := transformer.Execute() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("failed")) }) It("returns an error if fetching missing headers fails", func() { repository.SetMissingHeadersError(fakes.FakeError) err := transformer.Execute() + Expect(err).To(HaveOccurred()) }) It("gets missing headers for blocks between the configured block number range", func() { + repository.SetMissingHeaders(headers) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.StartingBlockNumber).To(Equal(flip_kick.FlipKickConfig.StartingBlockNumber)) - Expect(repository.EndingBlockNumber).To(Equal(flip_kick.FlipKickConfig.EndingBlockNumber)) + Expect(repository.PassedStartingBlockNumber).To(Equal(flip_kick.FlipKickConfig.StartingBlockNumber)) + Expect(repository.PassedEndingBlockNumber).To(Equal(flip_kick.FlipKickConfig.EndingBlockNumber)) }) }) diff --git a/pkg/transformers/integration_tests/flip_kick.go b/pkg/transformers/integration_tests/flip_kick.go index 5814084f..c0c263f5 100644 --- a/pkg/transformers/integration_tests/flip_kick.go +++ b/pkg/transformers/integration_tests/flip_kick.go @@ -18,12 +18,41 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/vulcanize/vulcanizedb/pkg/geth" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/test_config" "time" ) var _ = Describe("FlipKick Transformer", func() { + It("unpacks an event log", func() { + address := common.HexToAddress(shared.FlipperContractAddress) + abi, err := geth.ParseAbi(shared.FlipperABI) + Expect(err).NotTo(HaveOccurred()) + + contract := bind.NewBoundContract(address, abi, nil, nil, nil) + entity := &flip_kick.FlipKickEntity{} + + var eventLog = test_data.EthFlipKickLog + + err = contract.UnpackLog(entity, "Kick", eventLog) + Expect(err).NotTo(HaveOccurred()) + + expectedEntity := test_data.FlipKickEntity + Expect(entity.Id).To(Equal(expectedEntity.Id)) + Expect(entity.Lot).To(Equal(expectedEntity.Lot)) + Expect(entity.Bid).To(Equal(expectedEntity.Bid)) + Expect(entity.Gal).To(Equal(expectedEntity.Gal)) + Expect(entity.End).To(Equal(expectedEntity.End)) + Expect(entity.Urn).To(Equal(expectedEntity.Urn)) + Expect(entity.Tab).To(Equal(expectedEntity.Tab)) + }) + It("fetches and transforms a FlipKick event from Kovan chain", func() { blockNumber := int64(8956476) config := flip_kick.FlipKickConfig @@ -41,8 +70,13 @@ var _ = Describe("FlipKick Transformer", func() { err = persistHeader(db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := flip_kick.FlipKickTransformerInitializer{Config: config} - transformer := initializer.NewFlipKickTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: flip_kick.FlipKickConfig, + Converter: &flip_kick.FlipKickConverter{}, + Repository: &flip_kick.FlipKickRepository{}, + Fetcher: &shared.Fetcher{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/test_data/mocks/flip_kick/converter.go b/pkg/transformers/test_data/mocks/flip_kick/converter.go deleted file mode 100644 index f214b54b..00000000 --- a/pkg/transformers/test_data/mocks/flip_kick/converter.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018 Vulcanize -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package flip_kick - -import ( - "github.com/ethereum/go-ethereum/core/types" - - "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" - "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" -) - -type MockFlipKickConverter struct { - ConverterContracts []string - ConverterAbi string - LogsToConvert []types.Log - EntitiesToConvert []flip_kick.FlipKickEntity - ConverterError error -} - -func (mfkc *MockFlipKickConverter) ToEntities(contractAbi string, ethLogs []types.Log) ([]flip_kick.FlipKickEntity, error) { - for _, log := range ethLogs { - mfkc.ConverterContracts = append(mfkc.ConverterContracts, log.Address.Hex()) - } - mfkc.ConverterAbi = contractAbi - mfkc.LogsToConvert = append(mfkc.LogsToConvert, ethLogs...) - return []flip_kick.FlipKickEntity{test_data.FlipKickEntity}, mfkc.ConverterError -} - -func (mfkc *MockFlipKickConverter) ToModels(flipKickEntities []flip_kick.FlipKickEntity) ([]flip_kick.FlipKickModel, error) { - mfkc.EntitiesToConvert = append(mfkc.EntitiesToConvert, flipKickEntities...) - return []flip_kick.FlipKickModel{test_data.FlipKickModel}, nil -} - -func (mfkc *MockFlipKickConverter) SetConverterError(err error) { - mfkc.ConverterError = err -} diff --git a/pkg/transformers/test_data/mocks/flip_kick/repository.go b/pkg/transformers/test_data/mocks/flip_kick/repository.go deleted file mode 100644 index 633c487f..00000000 --- a/pkg/transformers/test_data/mocks/flip_kick/repository.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2018 Vulcanize -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package flip_kick - -import ( - . "github.com/onsi/gomega" - - "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" -) - -type MockFlipKickRepository struct { - CreateRecordError error - EndingBlockNumber int64 - FlipKicksCreated []flip_kick.FlipKickModel - HeaderIds []int64 - HeadersToReturn []core.Header - MissingHeadersError error - StartingBlockNumber int64 - markHeaderCheckedErr error - markHeaderCheckedPassedHeaderId int64 -} - -func (mfkr *MockFlipKickRepository) Create(headerId int64, flipKick []flip_kick.FlipKickModel) error { - mfkr.HeaderIds = append(mfkr.HeaderIds, headerId) - mfkr.FlipKicksCreated = append(mfkr.FlipKicksCreated, flipKick...) - - return mfkr.CreateRecordError -} - -func (mfkr *MockFlipKickRepository) MarkHeaderChecked(headerId int64) error { - mfkr.markHeaderCheckedPassedHeaderId = headerId - return mfkr.markHeaderCheckedErr -} - -func (mfkr *MockFlipKickRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { - mfkr.StartingBlockNumber = startingBlockNumber - mfkr.EndingBlockNumber = endingBlockNumber - - return mfkr.HeadersToReturn, mfkr.MissingHeadersError -} - -func (mfkr *MockFlipKickRepository) SetHeadersToReturn(headers []core.Header) { - mfkr.HeadersToReturn = headers -} - -func (mfkr *MockFlipKickRepository) SetCreateRecordError(err error) { - mfkr.CreateRecordError = err -} - -func (mfkr *MockFlipKickRepository) SetMarkHeaderCheckedErr(err error) { - mfkr.markHeaderCheckedErr = err -} - -func (mfkr *MockFlipKickRepository) SetMissingHeadersError(err error) { - mfkr.MissingHeadersError = err -} - -func (mfkr *MockFlipKickRepository) AssertMarkHeaderCheckedCalledWith(headerId int64) { - Expect(mfkr.markHeaderCheckedPassedHeaderId).To(Equal(headerId)) -} diff --git a/pkg/transformers/transformers.go b/pkg/transformers/transformers.go index 86e503d3..ecc9de59 100644 --- a/pkg/transformers/transformers.go +++ b/pkg/transformers/transformers.go @@ -118,8 +118,14 @@ var ( Fetcher: &shared.Fetcher{}, }.NewLogNoteTransformer - FlipKickTransformerInitializer = flip_kick.FlipKickTransformerInitializer{Config: flip_kick.FlipKickConfig}.NewFlipKickTransformer - FlogTransformerInitializer = factories.LogNoteTransformer{ + FlipKickTransformerInitializer = factories.Transformer{ + Config: flip_kick.FlipKickConfig, + Converter: &flip_kick.FlipKickConverter{}, + Repository: &flip_kick.FlipKickRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + FlogTransformerInitializer = factories.LogNoteTransformer{ Config: vow_flog.VowFlogConfig, Converter: &vow_flog.VowFlogConverter{}, Repository: &vow_flog.VowFlogRepository{},