diff --git a/cmd/continuousLogSync.go b/cmd/continuousLogSync.go index 6d8c66f7..dc09541e 100644 --- a/cmd/continuousLogSync.go +++ b/cmd/continuousLogSync.go @@ -86,33 +86,33 @@ func getTransformerInititalizers(transformerNames []string) []shared2.Transforme func buildTransformerInitializerMap() map[string]shared2.TransformerInitializer { transformerInitializerMap := make(map[string]shared2.TransformerInitializer) - transformerInitializerMap["bite"] = transformers.BiteTransformerInitializer - transformerInitializerMap["catFileChopLump"] = transformers.CatFileChopLumpTransformerInitializer - transformerInitializerMap["catFileFlip"] = transformers.CatFileFlipTransformerInitializer - transformerInitializerMap["catFilePitVow"] = transformers.CatFilePitVowTransformerInitializer - transformerInitializerMap["deal"] = transformers.DealTransformerInitializer - transformerInitializerMap["dent"] = transformers.DentTransformerInitializer - transformerInitializerMap["dripDrip"] = transformers.DripDripTransformerInitializer - transformerInitializerMap["dripFileIlk"] = transformers.DripFileIlkTransformerInitializer - transformerInitializerMap["dripFileRepo"] = transformers.DripFileRepoTransformerInitializer - transformerInitializerMap["dripFileVow"] = transformers.DripFileVowTransfromerInitializer - transformerInitializerMap["flipKick"] = transformers.FlipKickTransformerInitializer - transformerInitializerMap["flopKick"] = transformers.FlopKickTransformerInitializer - transformerInitializerMap["frob"] = transformers.FrobTransformerInitializer - transformerInitializerMap["pitFileDebtCeiling"] = transformers.PitFileDebtCeilingTransformerInitializer - transformerInitializerMap["pitFileIlk"] = transformers.PitFileIlkTransformerInitializer - transformerInitializerMap["pitFileStabilityFee"] = transformers.PitFileStabilityFeeTransformerInitializer - transformerInitializerMap["priceFeed"] = transformers.PriceFeedTransformerInitializer - transformerInitializerMap["tend"] = transformers.TendTransformerInitializer - transformerInitializerMap["vatGrab"] = transformers.VatGrabTransformerInitializer - transformerInitializerMap["vatInit"] = transformers.VatInitTransformerInitializer - transformerInitializerMap["vatMove"] = transformers.VatMoveTransformerInitializer - transformerInitializerMap["vatHeal"] = transformers.VatHealTransformerInitializer - transformerInitializerMap["vatFold"] = transformers.VatFoldTransformerInitializer - transformerInitializerMap["vatSlip"] = transformers.VatSlipTransformerInitializer - transformerInitializerMap["vatToll"] = transformers.VatTollTransformerInitializer - transformerInitializerMap["vatTune"] = transformers.VatTuneTransformerInitializer - transformerInitializerMap["vatFlux"] = transformers.VatFluxTransformerInitializer + transformerInitializerMap[shared2.BiteLabel] = transformers.BiteTransformerInitializer + transformerInitializerMap[shared2.CatFileChopLumpLabel] = transformers.CatFileChopLumpTransformerInitializer + transformerInitializerMap[shared2.CatFileFlipLabel] = transformers.CatFileFlipTransformerInitializer + transformerInitializerMap[shared2.CatFilePitVowLabel] = transformers.CatFilePitVowTransformerInitializer + transformerInitializerMap[shared2.DealLabel] = transformers.DealTransformerInitializer + transformerInitializerMap[shared2.DentLabel] = transformers.DentTransformerInitializer + transformerInitializerMap[shared2.DripDripLabel] = transformers.DripDripTransformerInitializer + transformerInitializerMap[shared2.DripFileIlkLabel] = transformers.DripFileIlkTransformerInitializer + transformerInitializerMap[shared2.DripFileRepoLabel] = transformers.DripFileRepoTransformerInitializer + transformerInitializerMap[shared2.DripFileVowLabel] = transformers.DripFileVowTransfromerInitializer + transformerInitializerMap[shared2.FlipKickLabel] = transformers.FlipKickTransformerInitializer + transformerInitializerMap[shared2.FlopKickLabel] = transformers.FlopKickTransformerInitializer + transformerInitializerMap[shared2.FrobLabel] = transformers.FrobTransformerInitializer + transformerInitializerMap[shared2.PitFileDebtCeilingLabel] = transformers.PitFileDebtCeilingTransformerInitializer + transformerInitializerMap[shared2.PitFileIlkLabel] = transformers.PitFileIlkTransformerInitializer + transformerInitializerMap[shared2.PitFileStabilityFeeLabel] = transformers.PitFileStabilityFeeTransformerInitializer + transformerInitializerMap[shared2.PriceFeedLabel] = transformers.PriceFeedTransformerInitializer + transformerInitializerMap[shared2.TendLabel] = transformers.TendTransformerInitializer + transformerInitializerMap[shared2.VatGrabLabel] = transformers.VatGrabTransformerInitializer + transformerInitializerMap[shared2.VatInitLabel] = transformers.VatInitTransformerInitializer + transformerInitializerMap[shared2.VatMoveLabel] = transformers.VatMoveTransformerInitializer + transformerInitializerMap[shared2.VatHealLabel] = transformers.VatHealTransformerInitializer + transformerInitializerMap[shared2.VatFoldLabel] = transformers.VatFoldTransformerInitializer + transformerInitializerMap[shared2.VatSlipLabel] = transformers.VatSlipTransformerInitializer + transformerInitializerMap[shared2.VatTollLabel] = transformers.VatTollTransformerInitializer + transformerInitializerMap[shared2.VatTuneLabel] = transformers.VatTuneTransformerInitializer + transformerInitializerMap[shared2.VatFluxLabel] = transformers.VatFluxTransformerInitializer return transformerInitializerMap } diff --git a/db/schema.sql b/db/schema.sql index 1445a09c..ed69d61a 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -2,8 +2,8 @@ -- PostgreSQL database dump -- --- Dumped from database version 10.3 --- Dumped by pg_dump version 10.3 +-- Dumped from database version 10.5 +-- Dumped by pg_dump version 10.5 SET statement_timeout = 0; SET lock_timeout = 0; diff --git a/pkg/transformers/drip_file/config.go b/pkg/transformers/drip_file/ilk/config.go similarity index 83% rename from pkg/transformers/drip_file/config.go rename to pkg/transformers/drip_file/ilk/config.go index 7acf5252..de6ad5ca 100644 --- a/pkg/transformers/drip_file/config.go +++ b/pkg/transformers/drip_file/ilk/config.go @@ -12,14 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -package drip_file +package ilk import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -var DripFileConfig = shared.TransformerConfig{ +var DripFileIlkConfig = shared.SingleTransformerConfig{ + TransformerName: shared.DripFileIlkLabel, ContractAddresses: []string{shared.DripContractAddress}, ContractAbi: shared.DripABI, - Topics: []string{shared.DripFileIlkSignature, shared.DripFileRepoSignature}, + Topic: shared.DripFileIlkSignature, StartingBlockNumber: 0, EndingBlockNumber: 10000000, } diff --git a/pkg/transformers/drip_file/ilk/converter.go b/pkg/transformers/drip_file/ilk/converter.go index 7620324e..4f03c473 100644 --- a/pkg/transformers/drip_file/ilk/converter.go +++ b/pkg/transformers/drip_file/ilk/converter.go @@ -24,19 +24,16 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]DripFileIlkModel, error) -} - type DripFileIlkConverter struct{} -func (DripFileIlkConverter) ToModels(ethLogs []types.Log) ([]DripFileIlkModel, error) { - var models []DripFileIlkModel +func (DripFileIlkConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { return nil, err } + ilk := string(bytes.Trim(ethLog.Topics[2].Bytes(), "\x00")) vow := string(bytes.Trim(ethLog.Topics[3].Bytes(), "\x00")) taxBytes := ethLog.Data[len(ethLog.Data)-shared.DataItemLength:] @@ -45,6 +42,7 @@ func (DripFileIlkConverter) ToModels(ethLogs []types.Log) ([]DripFileIlkModel, e if err != nil { return nil, err } + model := DripFileIlkModel{ Ilk: ilk, Vow: vow, diff --git a/pkg/transformers/drip_file/ilk/converter_test.go b/pkg/transformers/drip_file/ilk/converter_test.go index f7f48c9c..7d60ddc5 100644 --- a/pkg/transformers/drip_file/ilk/converter_test.go +++ b/pkg/transformers/drip_file/ilk/converter_test.go @@ -56,6 +56,6 @@ var _ = Describe("Drip file ilk converter", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(models)).To(Equal(1)) - Expect(models[0]).To(Equal(test_data.DripFileIlkModel)) + Expect(models[0].(ilk.DripFileIlkModel)).To(Equal(test_data.DripFileIlkModel)) }) }) diff --git a/pkg/transformers/drip_file/ilk/repository.go b/pkg/transformers/drip_file/ilk/repository.go index d9bad4fe..bde2d152 100644 --- a/pkg/transformers/drip_file/ilk/repository.go +++ b/pkg/transformers/drip_file/ilk/repository.go @@ -15,35 +15,34 @@ package ilk import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerID int64, models []DripFileIlkModel) error - MarkHeaderChecked(headerID int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type DripFileIlkRepository struct { db *postgres.DB } -func NewDripFileIlkRepository(db *postgres.DB) DripFileIlkRepository { - return DripFileIlkRepository{db: db} -} - -func (repository DripFileIlkRepository) Create(headerID int64, models []DripFileIlkModel) error { +func (repository DripFileIlkRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } + for _, model := range models { + ilk, ok := model.(DripFileIlkModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, DripFileIlkModel{}) + } + _, err = tx.Exec( `INSERT into maker.drip_file_ilk (header_id, ilk, vow, tax, log_idx, tx_idx, raw_log) - VALUES($1, $2, $3, $4::NUMERIC, $5, $6, $7)`, - headerID, model.Ilk, model.Vow, model.Tax, model.LogIndex, model.TransactionIndex, model.Raw, + VALUES($1, $2, $3, $4::NUMERIC, $5, $6, $7)`, + headerID, ilk.Ilk, ilk.Vow, ilk.Tax, ilk.LogIndex, ilk.TransactionIndex, ilk.Raw, ) + if err != nil { tx.Rollback() return err @@ -51,20 +50,21 @@ func (repository DripFileIlkRepository) Create(headerID int64, models []DripFile } _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, drip_file_ilk_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET drip_file_ilk_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET drip_file_ilk_checked = $2`, headerID, true) if err != nil { tx.Rollback() return err } + return tx.Commit() } func (repository DripFileIlkRepository) MarkHeaderChecked(headerID int64) error { _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, drip_file_ilk_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET drip_file_ilk_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET drip_file_ilk_checked = $2`, headerID, true) return err } @@ -73,14 +73,18 @@ func (repository DripFileIlkRepository) MissingHeaders(startingBlockNumber, endi err := repository.db.Select( &result, `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id - WHERE (header_id ISNULL OR drip_file_ilk_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, + LEFT JOIN checked_headers on headers.id = header_id + WHERE (header_id ISNULL OR drip_file_ilk_checked IS FALSE) + AND headers.block_number >= $1 + AND headers.block_number <= $2 + AND headers.eth_node_fingerprint = $3`, startingBlockNumber, endingBlockNumber, repository.db.Node.ID, ) return result, err } + +func (repository *DripFileIlkRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/drip_file/ilk/repository_test.go b/pkg/transformers/drip_file/ilk/repository_test.go index 359fc518..80245b95 100644 --- a/pkg/transformers/drip_file/ilk/repository_test.go +++ b/pkg/transformers/drip_file/ilk/repository_test.go @@ -16,10 +16,8 @@ package ilk_test import ( "database/sql" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" @@ -33,7 +31,7 @@ import ( var _ = Describe("Drip file ilk repository", func() { var ( db *postgres.DB - dripFileIlkRepository ilk.Repository + dripFileIlkRepository ilk.DripFileIlkRepository err error headerRepository datastore.HeaderRepository ) @@ -42,7 +40,8 @@ var _ = Describe("Drip file ilk repository", func() { db = test_config.NewTestDB(test_config.NewTestNode()) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - dripFileIlkRepository = ilk.NewDripFileIlkRepository(db) + dripFileIlkRepository = ilk.DripFileIlkRepository{} + dripFileIlkRepository.SetDB(db) }) Describe("Create", func() { @@ -52,7 +51,7 @@ var _ = Describe("Drip file ilk repository", func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = dripFileIlkRepository.Create(headerID, []ilk.DripFileIlkModel{test_data.DripFileIlkModel}) + err = dripFileIlkRepository.Create(headerID, []interface{}{test_data.DripFileIlkModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -69,7 +68,6 @@ var _ = Describe("Drip file ilk repository", func() { }) It("marks header as checked for logs", func() { - Expect(err).NotTo(HaveOccurred()) var headerChecked bool err = db.Get(&headerChecked, `SELECT drip_file_ilk_checked FROM public.checked_headers WHERE header_id = $1`, headerID) Expect(err).NotTo(HaveOccurred()) @@ -77,7 +75,7 @@ var _ = Describe("Drip file ilk repository", func() { }) It("does not duplicate drip file events", func() { - err = dripFileIlkRepository.Create(headerID, []ilk.DripFileIlkModel{test_data.DripFileIlkModel}) + err = dripFileIlkRepository.Create(headerID, []interface{}{test_data.DripFileIlkModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) @@ -92,6 +90,12 @@ var _ = Describe("Drip file ilk repository", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(sql.ErrNoRows)) }) + + It("Returns an error if model is of wrong type", func() { + err = dripFileIlkRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -139,12 +143,12 @@ var _ = Describe("Drip file ilk repository", func() { blockNumbers = []int64{startingBlock, dripFileBlock, endingBlock, endingBlock + 1} headerIDs = []int64{} + for _, n := range blockNumbers { headerID, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) headerIDs = append(headerIDs, headerID) } - }) It("returns headers with no associated drip file event", func() { @@ -179,7 +183,8 @@ var _ = Describe("Drip file ilk repository", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - dripFileIlkRepositoryTwo := ilk.NewDripFileIlkRepository(dbTwo) + dripFileIlkRepositoryTwo := ilk.DripFileIlkRepository{} + dripFileIlkRepositoryTwo.SetDB(dbTwo) err := dripFileIlkRepository.MarkHeaderChecked(headerIDs[0]) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/drip_file/ilk/transformer.go b/pkg/transformers/drip_file/ilk/transformer.go deleted file mode 100644 index d8a518f2..00000000 --- a/pkg/transformers/drip_file/ilk/transformer.go +++ /dev/null @@ -1,79 +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 ilk - -import ( - "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/drip_file" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -) - -type DripFileIlkTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -type DripFileIlkTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer DripFileIlkTransformerInitializer) NewDripFileIlkTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := DripFileIlkConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewDripFileIlkRepository(db) - return DripFileIlkTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -func (transformer DripFileIlkTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - log.Printf("Fetching drip file ilk event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.DripFileIlkSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(drip_file.DripFileConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - if len(matchingLogs) < 1 { - err = transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - model, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - err = transformer.Repository.Create(header.Id, model) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/drip_file/ilk/transformer_test.go b/pkg/transformers/drip_file/ilk/transformer_test.go index 3ad7194a..0bba4782 100644 --- a/pkg/transformers/drip_file/ilk/transformer_test.go +++ b/pkg/transformers/drip_file/ilk/transformer_test.go @@ -19,10 +19,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" @@ -31,31 +32,45 @@ import ( ) var _ = Describe("Drip file ilk transformer", func() { - It("gets missing headers for block numbers specified in config", func() { - repository := &ilk_mocks.MockDripFileIlkRepository{} - transformer := ilk.DripFileIlkTransformer{ - Config: drip_file.DripFileConfig, - Fetcher: &mocks.MockLogFetcher{}, - Converter: &ilk_mocks.MockDripFileIlkConverter{}, - Repository: repository, - } + var ( + config = ilk.DripFileIlkConfig + fetcher mocks.MockLogFetcher + converter ilk_mocks.MockDripFileIlkConverter + repository ilk_mocks.MockDripFileIlkRepository + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) + BeforeEach(func() { + fetcher = mocks.MockLogFetcher{} + converter = ilk_mocks.MockDripFileIlkConverter{} + repository = ilk_mocks.MockDripFileIlkRepository{} + transformer = factories.Transformer{ + Config: config, + Fetcher: &fetcher, + Converter: &converter, + Repository: &repository, + }.NewTransformer(nil, nil) + headerOne = core.Header{BlockNumber: rand.Int63(), Id: rand.Int63()} + headerTwo = core.Header{BlockNumber: rand.Int63(), Id: rand.Int63()} + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedStartingBlockNumber).To(Equal(drip_file.DripFileConfig.StartingBlockNumber)) - Expect(repository.PassedEndingBlockNumber).To(Equal(drip_file.DripFileConfig.EndingBlockNumber)) + Expect(repository.PassedStartingBlockNumber).To(Equal(config.StartingBlockNumber)) + Expect(repository.PassedEndingBlockNumber).To(Equal(config.EndingBlockNumber)) }) It("returns error if repository returns error for missing headers", func() { - repository := &ilk_mocks.MockDripFileIlkRepository{} - repository.SetMissingHeadersErr(fakes.FakeError) - transformer := ilk.DripFileIlkTransformer{ - Fetcher: &mocks.MockLogFetcher{}, - Converter: &ilk_mocks.MockDripFileIlkConverter{}, - Repository: repository, - } - + repository.SetMissingHeadersError(fakes.FakeError) err := transformer.Execute() Expect(err).To(HaveOccurred()) @@ -63,33 +78,18 @@ var _ = Describe("Drip file ilk transformer", func() { }) It("fetches logs for missing headers", func() { - fetcher := &mocks.MockLogFetcher{} - repository := &ilk_mocks.MockDripFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}, {BlockNumber: 2}}) - transformer := ilk.DripFileIlkTransformer{ - Fetcher: fetcher, - Converter: &ilk_mocks.MockDripFileIlkConverter{}, - Repository: repository, - } - + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) - Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{drip_file.DripFileConfig.ContractAddresses, drip_file.DripFileConfig.ContractAddresses})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) + Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{config.ContractAddresses, config.ContractAddresses})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.DripFileIlkSignature)}})) }) It("returns error if fetcher returns error", func() { - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetcherError(fakes.FakeError) - repository := &ilk_mocks.MockDripFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := ilk.DripFileIlkTransformer{ - Fetcher: fetcher, - Converter: &ilk_mocks.MockDripFileIlkConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -98,34 +98,16 @@ var _ = Describe("Drip file ilk transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &ilk_mocks.MockDripFileIlkConverter{} - mockRepository := &ilk_mocks.MockDripFileIlkRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := ilk.DripFileIlkTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } - + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &ilk_mocks.MockDripFileIlkConverter{} - mockRepository := &ilk_mocks.MockDripFileIlkRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := ilk.DripFileIlkTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedError(fakes.FakeError) err := transformer.Execute() @@ -134,16 +116,8 @@ var _ = Describe("Drip file ilk transformer", func() { }) It("converts matching logs", func() { - converter := &ilk_mocks.MockDripFileIlkConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileIlkLog}) - repository := &ilk_mocks.MockDripFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := ilk.DripFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -152,17 +126,9 @@ var _ = Describe("Drip file ilk transformer", func() { }) It("returns error if converter returns error", func() { - converter := &ilk_mocks.MockDripFileIlkConverter{} converter.SetConverterError(fakes.FakeError) - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileIlkLog}) - repository := &ilk_mocks.MockDripFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := ilk.DripFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -171,37 +137,20 @@ var _ = Describe("Drip file ilk transformer", func() { }) It("persists drip file model", func() { - converter := &ilk_mocks.MockDripFileIlkConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileIlkLog}) - repository := &ilk_mocks.MockDripFileIlkRepository{} - fakeHeader := core.Header{BlockNumber: 1, Id: 2} - repository.SetMissingHeaders([]core.Header{fakeHeader}) - transformer := ilk.DripFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) - Expect(repository.PassedModels).To(Equal([]ilk.DripFileIlkModel{test_data.DripFileIlkModel})) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.DripFileIlkModel})) }) It("returns error if repository returns error for create", func() { - converter := &ilk_mocks.MockDripFileIlkConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileIlkLog}) - repository := &ilk_mocks.MockDripFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}}) + repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := ilk.DripFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } err := transformer.Execute() diff --git a/pkg/transformers/drip_file/repo/config.go b/pkg/transformers/drip_file/repo/config.go new file mode 100644 index 00000000..c0609644 --- /dev/null +++ b/pkg/transformers/drip_file/repo/config.go @@ -0,0 +1,26 @@ +// 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 repo + +import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + +var DripFileRepoConfig = shared.SingleTransformerConfig{ + TransformerName: shared.DripFileRepoLabel, + ContractAddresses: []string{shared.DripContractAddress}, + ContractAbi: shared.DripABI, + Topic: shared.DripFileRepoSignature, + StartingBlockNumber: 0, + EndingBlockNumber: 10000000, +} diff --git a/pkg/transformers/drip_file/repo/converter.go b/pkg/transformers/drip_file/repo/converter.go index 8dfb29c6..ba4aa775 100644 --- a/pkg/transformers/drip_file/repo/converter.go +++ b/pkg/transformers/drip_file/repo/converter.go @@ -22,25 +22,23 @@ import ( "math/big" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]DripFileRepoModel, error) -} - type DripFileRepoConverter struct{} -func (DripFileRepoConverter) ToModels(ethLogs []types.Log) ([]DripFileRepoModel, error) { - var models []DripFileRepoModel +func (DripFileRepoConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { return nil, err } + what := string(bytes.Trim(ethLog.Topics[2].Bytes(), "\x00")) data := big.NewInt(0).SetBytes(ethLog.Topics[3].Bytes()).String() raw, err := json.Marshal(ethLog) if err != nil { return nil, err } + model := DripFileRepoModel{ What: what, Data: data, diff --git a/pkg/transformers/drip_file/repo/converter_test.go b/pkg/transformers/drip_file/repo/converter_test.go index 21ebc9fc..f2c9d223 100644 --- a/pkg/transformers/drip_file/repo/converter_test.go +++ b/pkg/transformers/drip_file/repo/converter_test.go @@ -44,6 +44,6 @@ var _ = Describe("Drip file repo converter", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(models)).To(Equal(1)) - Expect(models[0]).To(Equal(test_data.DripFileRepoModel)) + Expect(models[0].(repo.DripFileRepoModel)).To(Equal(test_data.DripFileRepoModel)) }) }) diff --git a/pkg/transformers/drip_file/repo/repository.go b/pkg/transformers/drip_file/repo/repository.go index 3ea04d13..e7e03cb1 100644 --- a/pkg/transformers/drip_file/repo/repository.go +++ b/pkg/transformers/drip_file/repo/repository.go @@ -15,56 +15,58 @@ package repo import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerID int64, models []DripFileRepoModel) error - MarkHeaderChecked(headerID int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type DripFileRepoRepository struct { db *postgres.DB } -func NewDripFileRepoRepository(db *postgres.DB) DripFileRepoRepository { - return DripFileRepoRepository{db: db} -} - -func (repository DripFileRepoRepository) Create(headerID int64, models []DripFileRepoModel) error { +func (repository DripFileRepoRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } + for _, model := range models { + repo, ok := model.(DripFileRepoModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, DripFileRepoModel{}) + } + _, err = tx.Exec( `INSERT into maker.drip_file_repo (header_id, what, data, log_idx, tx_idx, raw_log) - VALUES($1, $2, $3::NUMERIC, $4, $5, $6)`, - headerID, model.What, model.Data, model.LogIndex, model.TransactionIndex, model.Raw, + VALUES($1, $2, $3::NUMERIC, $4, $5, $6)`, + headerID, repo.What, repo.Data, repo.LogIndex, repo.TransactionIndex, repo.Raw, ) + if err != nil { tx.Rollback() return err } } + _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, drip_file_repo_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET drip_file_repo_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET drip_file_repo_checked = $2`, headerID, true) + if err != nil { tx.Rollback() return err } + return tx.Commit() } func (repository DripFileRepoRepository) MarkHeaderChecked(headerID int64) error { _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, drip_file_repo_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET drip_file_repo_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET drip_file_repo_checked = $2`, headerID, true) return err } @@ -73,14 +75,18 @@ func (repository DripFileRepoRepository) MissingHeaders(startingBlockNumber, end err := repository.db.Select( &result, `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id - WHERE (header_id ISNULL OR drip_file_repo_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, + LEFT JOIN checked_headers on headers.id = header_id + WHERE (header_id ISNULL OR drip_file_repo_checked IS FALSE) + AND headers.block_number >= $1 + AND headers.block_number <= $2 + AND headers.eth_node_fingerprint = $3`, startingBlockNumber, endingBlockNumber, repository.db.Node.ID, ) return result, err } + +func (repository *DripFileRepoRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/drip_file/repo/repository_test.go b/pkg/transformers/drip_file/repo/repository_test.go index 9973c0ac..6e63f901 100644 --- a/pkg/transformers/drip_file/repo/repository_test.go +++ b/pkg/transformers/drip_file/repo/repository_test.go @@ -16,6 +16,7 @@ package repo_test import ( "database/sql" + "math/rand" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -33,7 +34,7 @@ import ( var _ = Describe("Drip file repo repository", func() { var ( db *postgres.DB - dripFileRepoRepository repo.Repository + dripFileRepoRepository repo.DripFileRepoRepository err error headerRepository datastore.HeaderRepository ) @@ -42,7 +43,8 @@ var _ = Describe("Drip file repo repository", func() { db = test_config.NewTestDB(core.Node{}) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - dripFileRepoRepository = repo.NewDripFileRepoRepository(db) + dripFileRepoRepository = repo.DripFileRepoRepository{} + dripFileRepoRepository.SetDB(db) }) Describe("Create", func() { @@ -52,7 +54,7 @@ var _ = Describe("Drip file repo repository", func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = dripFileRepoRepository.Create(headerID, []repo.DripFileRepoModel{test_data.DripFileRepoModel}) + err = dripFileRepoRepository.Create(headerID, []interface{}{test_data.DripFileRepoModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -75,7 +77,7 @@ var _ = Describe("Drip file repo repository", func() { }) It("does not duplicate drip file events", func() { - err = dripFileRepoRepository.Create(headerID, []repo.DripFileRepoModel{test_data.DripFileRepoModel}) + err = dripFileRepoRepository.Create(headerID, []interface{}{test_data.DripFileRepoModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) @@ -90,6 +92,12 @@ var _ = Describe("Drip file repo repository", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(sql.ErrNoRows)) }) + + It("Returns an error if model is of wrong type", func() { + err = dripFileRepoRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -130,7 +138,7 @@ var _ = Describe("Drip file repo repository", func() { ) BeforeEach(func() { - startingBlock = GinkgoRandomSeed() + startingBlock = rand.Int63() dripFileBlock = startingBlock + 1 endingBlock = startingBlock + 2 @@ -176,7 +184,8 @@ var _ = Describe("Drip file repo repository", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - dripFileRepoRepositoryTwo := repo.NewDripFileRepoRepository(dbTwo) + dripFileRepoRepositoryTwo := repo.DripFileRepoRepository{} + dripFileRepoRepositoryTwo.SetDB(dbTwo) err := dripFileRepoRepository.MarkHeaderChecked(headerIDs[0]) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/drip_file/repo/transformer.go b/pkg/transformers/drip_file/repo/transformer.go deleted file mode 100644 index d34593dc..00000000 --- a/pkg/transformers/drip_file/repo/transformer.go +++ /dev/null @@ -1,79 +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 repo - -import ( - "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/drip_file" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -) - -type DripFileRepoTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -type DripFileRepoTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer DripFileRepoTransformerInitializer) NewDripFileRepoTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := DripFileRepoConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewDripFileRepoRepository(db) - return DripFileRepoTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -func (transformer DripFileRepoTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - log.Printf("Fetching drip file repo event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.DripFileRepoSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(drip_file.DripFileConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - if len(matchingLogs) < 1 { - err = transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - model, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - err = transformer.Repository.Create(header.Id, model) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/drip_file/repo/transformer_test.go b/pkg/transformers/drip_file/repo/transformer_test.go index 41fe09b8..e2dd912d 100644 --- a/pkg/transformers/drip_file/repo/transformer_test.go +++ b/pkg/transformers/drip_file/repo/transformer_test.go @@ -19,10 +19,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/repo" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" @@ -31,31 +32,45 @@ import ( ) var _ = Describe("Drip file repo transformer", func() { - It("gets missing headers for block numbers specified in config", func() { - repository := &repo_mocks.MockDripFileRepoRepository{} - transformer := repo.DripFileRepoTransformer{ - Config: drip_file.DripFileConfig, - Fetcher: &mocks.MockLogFetcher{}, - Converter: &repo_mocks.MockDripFileRepoConverter{}, - Repository: repository, - } + var ( + config = repo.DripFileRepoConfig + fetcher mocks.MockLogFetcher + converter repo_mocks.MockDripFileRepoConverter + repository repo_mocks.MockDripFileRepoRepository + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) + BeforeEach(func() { + fetcher = mocks.MockLogFetcher{} + converter = repo_mocks.MockDripFileRepoConverter{} + repository = repo_mocks.MockDripFileRepoRepository{} + transformer = factories.Transformer{ + Config: config, + Fetcher: &fetcher, + Converter: &converter, + Repository: &repository, + }.NewTransformer(nil, nil) + headerOne = core.Header{BlockNumber: rand.Int63(), Id: rand.Int63()} + headerTwo = core.Header{BlockNumber: rand.Int63(), Id: rand.Int63()} + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedStartingBlockNumber).To(Equal(drip_file.DripFileConfig.StartingBlockNumber)) - Expect(repository.PassedEndingBlockNumber).To(Equal(drip_file.DripFileConfig.EndingBlockNumber)) + Expect(repository.PassedStartingBlockNumber).To(Equal(config.StartingBlockNumber)) + Expect(repository.PassedEndingBlockNumber).To(Equal(config.EndingBlockNumber)) }) It("returns error if repository returns error for missing headers", func() { - repository := &repo_mocks.MockDripFileRepoRepository{} - repository.SetMissingHeadersErr(fakes.FakeError) - transformer := repo.DripFileRepoTransformer{ - Fetcher: &mocks.MockLogFetcher{}, - Converter: &repo_mocks.MockDripFileRepoConverter{}, - Repository: repository, - } - + repository.SetMissingHeadersError(fakes.FakeError) err := transformer.Execute() Expect(err).To(HaveOccurred()) @@ -63,33 +78,18 @@ var _ = Describe("Drip file repo transformer", func() { }) It("fetches logs for missing headers", func() { - fetcher := &mocks.MockLogFetcher{} - repository := &repo_mocks.MockDripFileRepoRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}, {BlockNumber: 2}}) - transformer := repo.DripFileRepoTransformer{ - Fetcher: fetcher, - Converter: &repo_mocks.MockDripFileRepoConverter{}, - Repository: repository, - } - + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) - Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{drip_file.DripFileConfig.ContractAddresses, drip_file.DripFileConfig.ContractAddresses})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) + Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{config.ContractAddresses, config.ContractAddresses})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.DripFileRepoSignature)}})) }) It("returns error if fetcher returns error", func() { - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetcherError(fakes.FakeError) - repository := &repo_mocks.MockDripFileRepoRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := repo.DripFileRepoTransformer{ - Fetcher: fetcher, - Converter: &repo_mocks.MockDripFileRepoConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -98,34 +98,16 @@ var _ = Describe("Drip file repo transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &repo_mocks.MockDripFileRepoConverter{} - mockRepository := &repo_mocks.MockDripFileRepoRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := repo.DripFileRepoTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } - + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &repo_mocks.MockDripFileRepoConverter{} - mockRepository := &repo_mocks.MockDripFileRepoRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := repo.DripFileRepoTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedError(fakes.FakeError) err := transformer.Execute() @@ -134,16 +116,8 @@ var _ = Describe("Drip file repo transformer", func() { }) It("converts matching logs", func() { - converter := &repo_mocks.MockDripFileRepoConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileRepoLog}) - repository := &repo_mocks.MockDripFileRepoRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := repo.DripFileRepoTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -152,17 +126,9 @@ var _ = Describe("Drip file repo transformer", func() { }) It("returns error if converter returns error", func() { - converter := &repo_mocks.MockDripFileRepoConverter{} converter.SetConverterError(fakes.FakeError) - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileRepoLog}) - repository := &repo_mocks.MockDripFileRepoRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := repo.DripFileRepoTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -171,37 +137,20 @@ var _ = Describe("Drip file repo transformer", func() { }) It("persists drip file model", func() { - converter := &repo_mocks.MockDripFileRepoConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileRepoLog}) - repository := &repo_mocks.MockDripFileRepoRepository{} - fakeHeader := core.Header{BlockNumber: 1, Id: 2} - repository.SetMissingHeaders([]core.Header{fakeHeader}) - transformer := repo.DripFileRepoTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) - Expect(repository.PassedModels).To(Equal([]repo.DripFileRepoModel{test_data.DripFileRepoModel})) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.DripFileRepoModel})) }) It("returns error if repository returns error for create", func() { - converter := &repo_mocks.MockDripFileRepoConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileRepoLog}) - repository := &repo_mocks.MockDripFileRepoRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}}) + repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := repo.DripFileRepoTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } err := transformer.Execute() diff --git a/pkg/transformers/drip_file/vow/config.go b/pkg/transformers/drip_file/vow/config.go new file mode 100644 index 00000000..1bd5e940 --- /dev/null +++ b/pkg/transformers/drip_file/vow/config.go @@ -0,0 +1,26 @@ +// 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 vow + +import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + +var DripFileVowConfig = shared.SingleTransformerConfig{ + TransformerName: shared.DripFileVowLabel, + ContractAddresses: []string{shared.DripContractAddress}, + ContractAbi: shared.DripABI, + Topic: shared.DripFileVowSignature, + StartingBlockNumber: 0, + EndingBlockNumber: 10000000, +} diff --git a/pkg/transformers/drip_file/vow/converter.go b/pkg/transformers/drip_file/vow/converter.go index c299d6ed..dac76194 100644 --- a/pkg/transformers/drip_file/vow/converter.go +++ b/pkg/transformers/drip_file/vow/converter.go @@ -22,25 +22,23 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]DripFileVowModel, error) -} - type DripFileVowConverter struct{} -func (DripFileVowConverter) ToModels(ethLogs []types.Log) ([]DripFileVowModel, error) { - var models []DripFileVowModel +func (DripFileVowConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { return nil, err } + what := string(bytes.Trim(ethLog.Topics[2].Bytes(), "\x00")) data := common.BytesToAddress(ethLog.Topics[3].Bytes()).String() raw, err := json.Marshal(ethLog) if err != nil { return nil, err } + model := DripFileVowModel{ What: what, Data: data, diff --git a/pkg/transformers/drip_file/vow/converter_test.go b/pkg/transformers/drip_file/vow/converter_test.go index 0458c611..8678b597 100644 --- a/pkg/transformers/drip_file/vow/converter_test.go +++ b/pkg/transformers/drip_file/vow/converter_test.go @@ -44,6 +44,6 @@ var _ = Describe("Drip file repo converter", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(models)).To(Equal(1)) - Expect(models[0]).To(Equal(test_data.DripFileVowModel)) + Expect(models[0].(vow.DripFileVowModel)).To(Equal(test_data.DripFileVowModel)) }) }) diff --git a/pkg/transformers/drip_file/vow/repository.go b/pkg/transformers/drip_file/vow/repository.go index bba93b65..32a4140a 100644 --- a/pkg/transformers/drip_file/vow/repository.go +++ b/pkg/transformers/drip_file/vow/repository.go @@ -15,56 +15,57 @@ package vow import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerID int64, models []DripFileVowModel) error - MarkHeaderChecked(headerID int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type DripFileVowRepository struct { db *postgres.DB } -func NewDripFileVowRepository(db *postgres.DB) DripFileVowRepository { - return DripFileVowRepository{db: db} -} - -func (repository DripFileVowRepository) Create(headerID int64, models []DripFileVowModel) error { +func (repository DripFileVowRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } + for _, model := range models { + vow, ok := model.(DripFileVowModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, DripFileVowModel{}) + } + _, err = tx.Exec( `INSERT into maker.drip_file_vow (header_id, what, data, log_idx, tx_idx, raw_log) - VALUES($1, $2, $3, $4, $5, $6)`, - headerID, model.What, model.Data, model.LogIndex, model.TransactionIndex, model.Raw, + VALUES($1, $2, $3, $4, $5, $6)`, + headerID, vow.What, vow.Data, vow.LogIndex, vow.TransactionIndex, vow.Raw, ) if err != nil { tx.Rollback() return err } } + _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, drip_file_vow_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET drip_file_vow_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET drip_file_vow_checked = $2`, headerID, true) + if err != nil { tx.Rollback() return err } + return tx.Commit() } func (repository DripFileVowRepository) MarkHeaderChecked(headerID int64) error { _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, drip_file_vow_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET drip_file_vow_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET drip_file_vow_checked = $2`, headerID, true) return err } @@ -73,14 +74,18 @@ func (repository DripFileVowRepository) MissingHeaders(startingBlockNumber, endi err := repository.db.Select( &result, `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id - WHERE (header_id ISNULL OR drip_file_vow_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, + LEFT JOIN checked_headers on headers.id = header_id + WHERE (header_id ISNULL OR drip_file_vow_checked IS FALSE) + AND headers.block_number >= $1 + AND headers.block_number <= $2 + AND headers.eth_node_fingerprint = $3`, startingBlockNumber, endingBlockNumber, repository.db.Node.ID, ) return result, err } + +func (repository *DripFileVowRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/drip_file/vow/repository_test.go b/pkg/transformers/drip_file/vow/repository_test.go index 96fde281..914f5fb6 100644 --- a/pkg/transformers/drip_file/vow/repository_test.go +++ b/pkg/transformers/drip_file/vow/repository_test.go @@ -16,6 +16,7 @@ package vow_test import ( "database/sql" + "math/rand" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -33,7 +34,7 @@ import ( var _ = Describe("Drip file vow repository", func() { var ( db *postgres.DB - dripFileVowRepository vow.Repository + dripFileVowRepository vow.DripFileVowRepository err error headerRepository datastore.HeaderRepository ) @@ -42,7 +43,8 @@ var _ = Describe("Drip file vow repository", func() { db = test_config.NewTestDB(core.Node{}) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - dripFileVowRepository = vow.NewDripFileVowRepository(db) + dripFileVowRepository = vow.DripFileVowRepository{} + dripFileVowRepository.SetDB(db) }) Describe("Create", func() { @@ -52,7 +54,7 @@ var _ = Describe("Drip file vow repository", func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = dripFileVowRepository.Create(headerID, []vow.DripFileVowModel{test_data.DripFileVowModel}) + err = dripFileVowRepository.Create(headerID, []interface{}{test_data.DripFileVowModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -75,7 +77,7 @@ var _ = Describe("Drip file vow repository", func() { }) It("does not duplicate drip file events", func() { - err = dripFileVowRepository.Create(headerID, []vow.DripFileVowModel{test_data.DripFileVowModel}) + err = dripFileVowRepository.Create(headerID, []interface{}{test_data.DripFileVowModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) @@ -90,6 +92,12 @@ var _ = Describe("Drip file vow repository", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(sql.ErrNoRows)) }) + + It("Returns an error if model is of wrong type", func() { + err = dripFileVowRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -130,7 +138,7 @@ var _ = Describe("Drip file vow repository", func() { ) BeforeEach(func() { - startingBlock = GinkgoRandomSeed() + startingBlock = rand.Int63() dripFileBlock = startingBlock + 1 endingBlock = startingBlock + 2 @@ -176,7 +184,8 @@ var _ = Describe("Drip file vow repository", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - dripFileVowRepositoryTwo := vow.NewDripFileVowRepository(dbTwo) + dripFileVowRepositoryTwo := vow.DripFileVowRepository{} + dripFileVowRepositoryTwo.SetDB(dbTwo) err := dripFileVowRepository.MarkHeaderChecked(headerIDs[0]) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/drip_file/vow/transformer.go b/pkg/transformers/drip_file/vow/transformer.go deleted file mode 100644 index bca52247..00000000 --- a/pkg/transformers/drip_file/vow/transformer.go +++ /dev/null @@ -1,79 +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 vow - -import ( - "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/drip_file" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -) - -type DripFileVowTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer DripFileVowTransformerInitializer) NewDripFileVowTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := DripFileVowConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewDripFileVowRepository(db) - return DripFileVowTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -type DripFileVowTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -func (transformer DripFileVowTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - log.Printf("Fetching drip file vow event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.DripFileVowSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(drip_file.DripFileConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - if len(matchingLogs) < 1 { - err = transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - model, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - err = transformer.Repository.Create(header.Id, model) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/drip_file/vow/transformer_test.go b/pkg/transformers/drip_file/vow/transformer_test.go index eb55c3e1..451bb6d1 100644 --- a/pkg/transformers/drip_file/vow/transformer_test.go +++ b/pkg/transformers/drip_file/vow/transformer_test.go @@ -19,10 +19,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" @@ -31,31 +32,45 @@ import ( ) var _ = Describe("Drip file vow transformer", func() { - It("gets missing headers for block numbers specified in config", func() { - repository := &vow_mocks.MockDripFileVowRepository{} - transformer := vow.DripFileVowTransformer{ - Config: drip_file.DripFileConfig, - Fetcher: &mocks.MockLogFetcher{}, - Converter: &vow_mocks.MockDripFileVowConverter{}, - Repository: repository, - } + var ( + config = vow.DripFileVowConfig + fetcher mocks.MockLogFetcher + converter vow_mocks.MockDripFileVowConverter + repository vow_mocks.MockDripFileVowRepository + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) + BeforeEach(func() { + fetcher = mocks.MockLogFetcher{} + converter = vow_mocks.MockDripFileVowConverter{} + repository = vow_mocks.MockDripFileVowRepository{} + transformer = factories.Transformer{ + Config: config, + Fetcher: &fetcher, + Converter: &converter, + Repository: &repository, + }.NewTransformer(nil, nil) + headerOne = core.Header{BlockNumber: rand.Int63(), Id: rand.Int63()} + headerTwo = core.Header{BlockNumber: rand.Int63(), Id: rand.Int63()} + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedStartingBlockNumber).To(Equal(drip_file.DripFileConfig.StartingBlockNumber)) - Expect(repository.PassedEndingBlockNumber).To(Equal(drip_file.DripFileConfig.EndingBlockNumber)) + Expect(repository.PassedStartingBlockNumber).To(Equal(config.StartingBlockNumber)) + Expect(repository.PassedEndingBlockNumber).To(Equal(config.EndingBlockNumber)) }) It("returns error if repository returns error for missing headers", func() { - repository := &vow_mocks.MockDripFileVowRepository{} - repository.SetMissingHeadersErr(fakes.FakeError) - transformer := vow.DripFileVowTransformer{ - Fetcher: &mocks.MockLogFetcher{}, - Converter: &vow_mocks.MockDripFileVowConverter{}, - Repository: repository, - } - + repository.SetMissingHeadersError(fakes.FakeError) err := transformer.Execute() Expect(err).To(HaveOccurred()) @@ -63,33 +78,18 @@ var _ = Describe("Drip file vow transformer", func() { }) It("fetches logs for missing headers", func() { - fetcher := &mocks.MockLogFetcher{} - repository := &vow_mocks.MockDripFileVowRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}, {BlockNumber: 2}}) - transformer := vow.DripFileVowTransformer{ - Fetcher: fetcher, - Converter: &vow_mocks.MockDripFileVowConverter{}, - Repository: repository, - } - + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) - Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{drip_file.DripFileConfig.ContractAddresses, drip_file.DripFileConfig.ContractAddresses})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) + Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{config.ContractAddresses, config.ContractAddresses})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.DripFileVowSignature)}})) }) It("returns error if fetcher returns error", func() { - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetcherError(fakes.FakeError) - repository := &vow_mocks.MockDripFileVowRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := vow.DripFileVowTransformer{ - Fetcher: fetcher, - Converter: &vow_mocks.MockDripFileVowConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -98,34 +98,16 @@ var _ = Describe("Drip file vow transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &vow_mocks.MockDripFileVowConverter{} - mockRepository := &vow_mocks.MockDripFileVowRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := vow.DripFileVowTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } - + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &vow_mocks.MockDripFileVowConverter{} - mockRepository := &vow_mocks.MockDripFileVowRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := vow.DripFileVowTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedError(fakes.FakeError) err := transformer.Execute() @@ -134,16 +116,8 @@ var _ = Describe("Drip file vow transformer", func() { }) It("converts matching logs", func() { - converter := &vow_mocks.MockDripFileVowConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileVowLog}) - repository := &vow_mocks.MockDripFileVowRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := vow.DripFileVowTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -152,17 +126,9 @@ var _ = Describe("Drip file vow transformer", func() { }) It("returns error if converter returns error", func() { - converter := &vow_mocks.MockDripFileVowConverter{} converter.SetConverterError(fakes.FakeError) - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileVowLog}) - repository := &vow_mocks.MockDripFileVowRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := vow.DripFileVowTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -171,37 +137,20 @@ var _ = Describe("Drip file vow transformer", func() { }) It("persists drip file model", func() { - converter := &vow_mocks.MockDripFileVowConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileVowLog}) - repository := &vow_mocks.MockDripFileVowRepository{} - fakeHeader := core.Header{BlockNumber: 1, Id: 2} - repository.SetMissingHeaders([]core.Header{fakeHeader}) - transformer := vow.DripFileVowTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) - Expect(repository.PassedModels).To(Equal([]vow.DripFileVowModel{test_data.DripFileVowModel})) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.DripFileVowModel})) }) It("returns error if repository returns error for create", func() { - converter := &vow_mocks.MockDripFileVowConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthDripFileVowLog}) - repository := &vow_mocks.MockDripFileVowRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}}) + repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := vow.DripFileVowTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } err := transformer.Execute() diff --git a/pkg/transformers/factories/transformer.go b/pkg/transformers/factories/transformer.go new file mode 100644 index 00000000..93c7048e --- /dev/null +++ b/pkg/transformers/factories/transformer.go @@ -0,0 +1,97 @@ +// 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 factories + +import ( + "github.com/ethereum/go-ethereum/core/types" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "log" + + "github.com/ethereum/go-ethereum/common" + + "github.com/vulcanize/vulcanizedb/pkg/core" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" +) + +type Transformer struct { + Config shared.SingleTransformerConfig + Converter Converter + Repository Repository + Fetcher shared.SettableLogFetcher +} + +type Converter interface { + ToModels(ethLog []types.Log) ([]interface{}, error) +} + +type Repository interface { + Create(headerID int64, models []interface{}) error + MarkHeaderChecked(headerID int64) error + MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) + SetDB(db *postgres.DB) +} + +func (transformer Transformer) NewTransformer(db *postgres.DB, bc core.BlockChain) shared.Transformer { + transformer.Repository.SetDB(db) + transformer.Fetcher.SetBC(bc) + return transformer +} + +func (transformer Transformer) Execute() error { + transformerName := transformer.Config.TransformerName + missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) + if err != nil { + log.Printf("Error fetching mising headers in %v transformer: %v \n", transformerName, err) + return err + } + + // Grab event signature from transformer config + // (Double-array structure required for go-ethereum FilterQuery) + var topic = [][]common.Hash{{common.HexToHash(transformer.Config.Topic)}} + + log.Printf("Fetching %v event logs for %d headers \n", transformerName, len(missingHeaders)) + for _, header := range missingHeaders { + // Fetch the missing logs for a given header + matchingLogs, err := transformer.Fetcher.FetchLogs(transformer.Config.ContractAddresses, topic, header.BlockNumber) + if err != nil { + log.Printf("Error fetching matching logs in %v transformer: %v", transformerName, err) + return err + } + + // No matching logs, mark the header as checked for this type of logs + if len(matchingLogs) < 1 { + err := transformer.Repository.MarkHeaderChecked(header.Id) + if err != nil { + log.Printf("Error marking header as checked in %v: %v", transformerName, err) + return err + } + // Continue with the next header; nothing to persist + continue + } + + models, err := transformer.Converter.ToModels(matchingLogs) + if err != nil { + log.Printf("Error converting logs in %v: %v", transformerName, err) + return err + } + + err = transformer.Repository.Create(header.Id, models) + if err != nil { + log.Printf("Error persisting %v record: %v", transformerName, err) + return err + } + } + return nil +} diff --git a/pkg/transformers/integration_tests/drip_file_vow.go b/pkg/transformers/integration_tests/drip_file_vow.go index 7a849410..eacf35a8 100644 --- a/pkg/transformers/integration_tests/drip_file_vow.go +++ b/pkg/transformers/integration_tests/drip_file_vow.go @@ -17,8 +17,9 @@ package integration_tests import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -26,7 +27,7 @@ import ( var _ = Describe("Drip File Vow Transformer", func() { It("transforms DripFileVow log events", func() { blockNumber := int64(8762197) - config := drip_file.DripFileConfig + config := vow.DripFileVowConfig config.StartingBlockNumber = blockNumber config.EndingBlockNumber = blockNumber @@ -41,8 +42,13 @@ var _ = Describe("Drip File Vow Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := vow.DripFileVowTransformerInitializer{Config: config} - transformer := initializer.NewDripFileVowTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &vow.DripFileVowConverter{}, + Repository: &vow.DripFileVowRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/pit_file_debt_ceiling.go b/pkg/transformers/integration_tests/pit_file_debt_ceiling.go index 6c7bd92b..711e8857 100644 --- a/pkg/transformers/integration_tests/pit_file_debt_ceiling.go +++ b/pkg/transformers/integration_tests/pit_file_debt_ceiling.go @@ -17,8 +17,9 @@ package integration_tests import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -26,7 +27,7 @@ import ( var _ = Describe("PitFileDebtCeiling Transformer", func() { It("fetches and transforms a PitFileDebtCeiling event from Kovan chain", func() { blockNumber := int64(8535578) - config := pit_file.PitFileConfig + config := debt_ceiling.DebtCeilingFileConfig config.StartingBlockNumber = blockNumber config.EndingBlockNumber = blockNumber @@ -41,8 +42,13 @@ var _ = Describe("PitFileDebtCeiling Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := debt_ceiling.PitFileDebtCeilingTransformerInitializer{Config: config} - transformer := initializer.NewPitFileDebtCeilingTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &debt_ceiling.PitFileDebtCeilingConverter{}, + Repository: &debt_ceiling.PitFileDebtCeilingRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/pit_file_ilk.go b/pkg/transformers/integration_tests/pit_file_ilk.go index 3c820c10..c9726b35 100644 --- a/pkg/transformers/integration_tests/pit_file_ilk.go +++ b/pkg/transformers/integration_tests/pit_file_ilk.go @@ -17,8 +17,9 @@ package integration_tests import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -26,7 +27,7 @@ import ( var _ = Describe("PitFileIlk Transformer", func() { It("fetches and transforms a PitFileIlk event from Kovan chain", func() { blockNumber := int64(9103223) - config := pit_file.PitFileConfig + config := ilk.IlkFileConfig config.StartingBlockNumber = blockNumber config.EndingBlockNumber = blockNumber @@ -41,8 +42,13 @@ var _ = Describe("PitFileIlk Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := ilk.PitFileIlkTransformerInitializer{Config: config} - transformer := initializer.NewPitFileIlkTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &ilk.PitFileIlkConverter{}, + Repository: &ilk.PitFileIlkRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/pit_file_stability_fee.go b/pkg/transformers/integration_tests/pit_file_stability_fee.go index 39220585..2c1f84ff 100644 --- a/pkg/transformers/integration_tests/pit_file_stability_fee.go +++ b/pkg/transformers/integration_tests/pit_file_stability_fee.go @@ -17,8 +17,9 @@ package integration_tests import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee" "github.com/vulcanize/vulcanizedb/test_config" ) @@ -26,7 +27,7 @@ import ( var _ = Describe("PitFileStabilityFee Transformer", func() { It("fetches and transforms a PitFileStabilityFee event from Kovan chain", func() { blockNumber := int64(8535544) - config := pit_file.PitFileConfig + config := stability_fee.StabilityFeeFileConfig config.StartingBlockNumber = blockNumber config.EndingBlockNumber = blockNumber @@ -41,8 +42,13 @@ var _ = Describe("PitFileStabilityFee Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := stability_fee.PitFileStabilityFeeTransformerInitializer{Config: config} - transformer := initializer.NewPitFileStabilityFeeTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &stability_fee.PitFileStabilityFeeConverter{}, + Repository: &stability_fee.PitFileStabilityFeeRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/tend.go b/pkg/transformers/integration_tests/tend.go index bacaed03..23b49558 100644 --- a/pkg/transformers/integration_tests/tend.go +++ b/pkg/transformers/integration_tests/tend.go @@ -17,6 +17,8 @@ package integration_tests import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/tend" "github.com/vulcanize/vulcanizedb/test_config" @@ -40,8 +42,13 @@ var _ = Describe("Tend Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := tend.TendTransformerInitializer{Config: config} - transformer := initializer.NewTendTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &tend.TendConverter{}, + Repository: &tend.TendRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) @@ -74,8 +81,13 @@ var _ = Describe("Tend Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := tend.TendTransformerInitializer{Config: config} - transformer := initializer.NewTendTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &tend.TendConverter{}, + Repository: &tend.TendRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_init.go b/pkg/transformers/integration_tests/vat_init.go index d1b78931..fba6fb72 100644 --- a/pkg/transformers/integration_tests/vat_init.go +++ b/pkg/transformers/integration_tests/vat_init.go @@ -17,6 +17,8 @@ package integration_tests import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_init" "github.com/vulcanize/vulcanizedb/test_config" @@ -40,8 +42,13 @@ var _ = Describe("VatInit Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := vat_init.VatInitTransformerInitializer{Config: config} - transformer := initializer.NewVatInitTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &vat_init.VatInitConverter{}, + Repository: &vat_init.VatInitRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/integration_tests/vat_move.go b/pkg/transformers/integration_tests/vat_move.go index 7f93985e..0992324b 100644 --- a/pkg/transformers/integration_tests/vat_move.go +++ b/pkg/transformers/integration_tests/vat_move.go @@ -18,6 +18,8 @@ import ( "github.com/ethereum/go-ethereum/common" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move" "github.com/vulcanize/vulcanizedb/test_config" @@ -41,8 +43,13 @@ var _ = Describe("VatMove Transformer", func() { err = persistHeader(rpcClient, db, blockNumber) Expect(err).NotTo(HaveOccurred()) - initializer := vat_move.VatMoveTransformerInitializer{Config: config} - transformer := initializer.NewVatMoveTransformer(db, blockchain) + initializer := factories.Transformer{ + Config: config, + Fetcher: &shared.Fetcher{}, + Converter: &vat_move.VatMoveConverter{}, + Repository: &vat_move.VatMoveRepository{}, + } + transformer := initializer.NewTransformer(db, blockchain) err = transformer.Execute() Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/pit_file/config.go b/pkg/transformers/pit_file/debt_ceiling/config.go similarity index 80% rename from pkg/transformers/pit_file/config.go rename to pkg/transformers/pit_file/debt_ceiling/config.go index 73656bd4..52dae6fc 100644 --- a/pkg/transformers/pit_file/config.go +++ b/pkg/transformers/pit_file/debt_ceiling/config.go @@ -12,16 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -package pit_file +package debt_ceiling import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) -var PitFileConfig = shared.TransformerConfig{ +var DebtCeilingFileConfig = shared.SingleTransformerConfig{ + TransformerName: shared.PitFileDebtCeilingLabel, ContractAddresses: []string{shared.PitContractAddress}, ContractAbi: shared.PitABI, - Topics: []string{shared.PitFileIlkSignature, shared.PitFileDebtCeilingSignature, shared.PitFileStabilityFeeSignature}, + Topic: shared.PitFileDebtCeilingSignature, StartingBlockNumber: 0, EndingBlockNumber: 10000000, } diff --git a/pkg/transformers/pit_file/debt_ceiling/converter.go b/pkg/transformers/pit_file/debt_ceiling/converter.go index f47044f3..620644a8 100644 --- a/pkg/transformers/pit_file/debt_ceiling/converter.go +++ b/pkg/transformers/pit_file/debt_ceiling/converter.go @@ -24,14 +24,10 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]PitFileDebtCeilingModel, error) -} - type PitFileDebtCeilingConverter struct{} -func (PitFileDebtCeilingConverter) ToModels(ethLogs []types.Log) ([]PitFileDebtCeilingModel, error) { - var models []PitFileDebtCeilingModel +func (PitFileDebtCeilingConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { diff --git a/pkg/transformers/pit_file/debt_ceiling/converter_test.go b/pkg/transformers/pit_file/debt_ceiling/converter_test.go index fec50524..2ed70a59 100644 --- a/pkg/transformers/pit_file/debt_ceiling/converter_test.go +++ b/pkg/transformers/pit_file/debt_ceiling/converter_test.go @@ -17,10 +17,10 @@ package debt_ceiling_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) @@ -54,6 +54,6 @@ var _ = Describe("Pit file debt ceiling converter", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(models)).To(Equal(1)) - Expect(models[0]).To(Equal(test_data.PitFileDebtCeilingModel)) + Expect(models[0].(debt_ceiling.PitFileDebtCeilingModel)).To(Equal(test_data.PitFileDebtCeilingModel)) }) }) diff --git a/pkg/transformers/pit_file/debt_ceiling/repository.go b/pkg/transformers/pit_file/debt_ceiling/repository.go index a5e86335..14b59c16 100644 --- a/pkg/transformers/pit_file/debt_ceiling/repository.go +++ b/pkg/transformers/pit_file/debt_ceiling/repository.go @@ -15,58 +15,58 @@ package debt_ceiling import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerID int64, models []PitFileDebtCeilingModel) error - MarkHeaderChecked(headerID int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type PitFileDebtCeilingRepository struct { db *postgres.DB } -func NewPitFileDebtCeilingRepository(db *postgres.DB) PitFileDebtCeilingRepository { - return PitFileDebtCeilingRepository{ - db: db, - } -} - -func (repository PitFileDebtCeilingRepository) Create(headerID int64, models []PitFileDebtCeilingModel) error { +func (repository PitFileDebtCeilingRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } + for _, model := range models { + pitFileDC, ok := model.(PitFileDebtCeilingModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, PitFileDebtCeilingModel{}) + } + _, err = tx.Exec( `INSERT into maker.pit_file_debt_ceiling (header_id, what, data, tx_idx, raw_log) VALUES($1, $2, $3::NUMERIC, $4, $5)`, - headerID, model.What, model.Data, model.TransactionIndex, model.Raw, + headerID, pitFileDC.What, pitFileDC.Data, pitFileDC.TransactionIndex, pitFileDC.Raw, ) + if err != nil { tx.Rollback() return err } } + _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, pit_file_debt_ceiling_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET pit_file_debt_ceiling_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET pit_file_debt_ceiling_checked = $2`, headerID, true) + if err != nil { tx.Rollback() return err } + return tx.Commit() } func (repository PitFileDebtCeilingRepository) MarkHeaderChecked(headerID int64) error { _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, pit_file_debt_ceiling_checked) VALUES ($1, $2) - ON CONFLICT (header_id) DO - UPDATE SET pit_file_debt_ceiling_checked = $2`, headerID, true) + ON CONFLICT (header_id) DO + UPDATE SET pit_file_debt_ceiling_checked = $2`, headerID, true) return err } @@ -75,14 +75,18 @@ func (repository PitFileDebtCeilingRepository) MissingHeaders(startingBlockNumbe err := repository.db.Select( &result, `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id + LEFT JOIN checked_headers on headers.id = header_id WHERE (header_id ISNULL OR pit_file_debt_ceiling_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, + AND headers.block_number >= $1 + AND headers.block_number <= $2 + AND headers.eth_node_fingerprint = $3`, startingBlockNumber, endingBlockNumber, repository.db.Node.ID, ) return result, err } + +func (repository *PitFileDebtCeilingRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/pit_file/debt_ceiling/repository_test.go b/pkg/transformers/pit_file/debt_ceiling/repository_test.go index dd2d729a..23b0da01 100644 --- a/pkg/transformers/pit_file/debt_ceiling/repository_test.go +++ b/pkg/transformers/pit_file/debt_ceiling/repository_test.go @@ -16,6 +16,7 @@ package debt_ceiling_test import ( "database/sql" + "math/rand" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -32,17 +33,18 @@ import ( var _ = Describe("Pit file debt ceiling repository", func() { var ( - db *postgres.DB - pitFileRepository debt_ceiling.Repository - err error - headerRepository datastore.HeaderRepository + db *postgres.DB + pitFileDebtCeilingRepository debt_ceiling.PitFileDebtCeilingRepository + err error + headerRepository datastore.HeaderRepository ) BeforeEach(func() { db = test_config.NewTestDB(core.Node{}) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - pitFileRepository = debt_ceiling.NewPitFileDebtCeilingRepository(db) + pitFileDebtCeilingRepository = debt_ceiling.PitFileDebtCeilingRepository{} + pitFileDebtCeilingRepository.SetDB(db) }) Describe("Create", func() { @@ -52,7 +54,7 @@ var _ = Describe("Pit file debt ceiling repository", func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = pitFileRepository.Create(headerID, []debt_ceiling.PitFileDebtCeilingModel{test_data.PitFileDebtCeilingModel}) + err = pitFileDebtCeilingRepository.Create(headerID, []interface{}{test_data.PitFileDebtCeilingModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -74,7 +76,7 @@ var _ = Describe("Pit file debt ceiling repository", func() { }) It("does not duplicate pit file events", func() { - err = pitFileRepository.Create(headerID, []debt_ceiling.PitFileDebtCeilingModel{test_data.PitFileDebtCeilingModel}) + err = pitFileDebtCeilingRepository.Create(headerID, []interface{}{test_data.PitFileDebtCeilingModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) @@ -89,6 +91,12 @@ var _ = Describe("Pit file debt ceiling repository", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(sql.ErrNoRows)) }) + + It("Returns an error if model is of wrong type", func() { + err = pitFileDebtCeilingRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -100,7 +108,7 @@ var _ = Describe("Pit file debt ceiling repository", func() { }) It("creates a row for a new headerID", func() { - err = pitFileRepository.MarkHeaderChecked(headerID) + err = pitFileDebtCeilingRepository.MarkHeaderChecked(headerID) Expect(err).NotTo(HaveOccurred()) var headerChecked bool @@ -112,7 +120,7 @@ var _ = Describe("Pit file debt ceiling repository", func() { It("updates row when headerID already exists", func() { _, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerID) - err = pitFileRepository.MarkHeaderChecked(headerID) + err = pitFileDebtCeilingRepository.MarkHeaderChecked(headerID) Expect(err).NotTo(HaveOccurred()) var headerChecked bool @@ -129,7 +137,7 @@ var _ = Describe("Pit file debt ceiling repository", func() { ) BeforeEach(func() { - startingBlock = GinkgoRandomSeed() + startingBlock = rand.Int63() pitFileBlock = startingBlock + 1 endingBlock = startingBlock + 2 @@ -144,10 +152,11 @@ var _ = Describe("Pit file debt ceiling repository", func() { }) It("returns headers that haven't been checked", func() { - err := pitFileRepository.MarkHeaderChecked(headerIDs[1]) + + err := pitFileDebtCeilingRepository.MarkHeaderChecked(headerIDs[1]) Expect(err).NotTo(HaveOccurred()) - headers, err := pitFileRepository.MissingHeaders(startingBlock, endingBlock) + headers, err := pitFileDebtCeilingRepository.MissingHeaders(startingBlock, endingBlock) Expect(err).NotTo(HaveOccurred()) Expect(len(headers)).To(Equal(2)) @@ -159,7 +168,7 @@ var _ = Describe("Pit file debt ceiling repository", func() { _, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerIDs[1]) Expect(err).NotTo(HaveOccurred()) - headers, err := pitFileRepository.MissingHeaders(startingBlock, endingBlock) + headers, err := pitFileDebtCeilingRepository.MissingHeaders(startingBlock, endingBlock) Expect(err).NotTo(HaveOccurred()) Expect(len(headers)).To(Equal(3)) @@ -175,16 +184,16 @@ var _ = Describe("Pit file debt ceiling repository", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - pitFileRepository := debt_ceiling.NewPitFileDebtCeilingRepository(db) - pitFileRepositoryTwo := debt_ceiling.NewPitFileDebtCeilingRepository(dbTwo) - err := pitFileRepository.MarkHeaderChecked(headerIDs[0]) + pitFileDebtCeilingRepositoryTwo := debt_ceiling.PitFileDebtCeilingRepository{} + pitFileDebtCeilingRepositoryTwo.SetDB(dbTwo) + err := pitFileDebtCeilingRepository.MarkHeaderChecked(headerIDs[0]) Expect(err).NotTo(HaveOccurred()) - nodeOneMissingHeaders, err := pitFileRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) + nodeOneMissingHeaders, err := pitFileDebtCeilingRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) Expect(err).NotTo(HaveOccurred()) Expect(len(nodeOneMissingHeaders)).To(Equal(len(blockNumbers) - 1)) - nodeTwoMissingHeaders, err := pitFileRepositoryTwo.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) + nodeTwoMissingHeaders, err := pitFileDebtCeilingRepositoryTwo.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) Expect(err).NotTo(HaveOccurred()) Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers))) }) diff --git a/pkg/transformers/pit_file/debt_ceiling/transformer.go b/pkg/transformers/pit_file/debt_ceiling/transformer.go deleted file mode 100644 index a82b2eff..00000000 --- a/pkg/transformers/pit_file/debt_ceiling/transformer.go +++ /dev/null @@ -1,79 +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 debt_ceiling - -import ( - "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/pit_file" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -) - -type PitFileDebtCeilingTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -type PitFileDebtCeilingTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer PitFileDebtCeilingTransformerInitializer) NewPitFileDebtCeilingTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := PitFileDebtCeilingConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewPitFileDebtCeilingRepository(db) - return PitFileDebtCeilingTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -func (transformer PitFileDebtCeilingTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - log.Printf("Fetching pit file debt ceiling event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.PitFileDebtCeilingSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(pit_file.PitFileConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - if len(matchingLogs) < 1 { - err = transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - model, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - err = transformer.Repository.Create(header.Id, model) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/pit_file/debt_ceiling/transformer_test.go b/pkg/transformers/pit_file/debt_ceiling/transformer_test.go index 89dc5b67..ede2708d 100644 --- a/pkg/transformers/pit_file/debt_ceiling/transformer_test.go +++ b/pkg/transformers/pit_file/debt_ceiling/transformer_test.go @@ -19,10 +19,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" @@ -31,31 +32,45 @@ import ( ) var _ = Describe("Pit file debt ceiling transformer", func() { - It("gets missing headers for block numbers specified in config", func() { - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Config: pit_file.PitFileConfig, - Fetcher: &mocks.MockLogFetcher{}, - Converter: &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{}, - Repository: repository, - } + var ( + config = debt_ceiling.DebtCeilingFileConfig + fetcher mocks.MockLogFetcher + converter debt_ceiling_mocks.MockPitFileDebtCeilingConverter + repository debt_ceiling_mocks.MockPitFileDebtCeilingRepository + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) + BeforeEach(func() { + fetcher = mocks.MockLogFetcher{} + converter = debt_ceiling_mocks.MockPitFileDebtCeilingConverter{} + repository = debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} + headerOne = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + headerTwo = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + transformer = factories.Transformer{ + Config: config, + Fetcher: &fetcher, + Converter: &converter, + Repository: &repository, + }.NewTransformer(nil, nil) + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedStartingBlockNumber).To(Equal(pit_file.PitFileConfig.StartingBlockNumber)) - Expect(repository.PassedEndingBlockNumber).To(Equal(pit_file.PitFileConfig.EndingBlockNumber)) + Expect(repository.PassedStartingBlockNumber).To(Equal(config.StartingBlockNumber)) + Expect(repository.PassedEndingBlockNumber).To(Equal(config.EndingBlockNumber)) }) It("returns error if repository returns error for missing headers", func() { - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - repository.SetMissingHeadersErr(fakes.FakeError) - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Fetcher: &mocks.MockLogFetcher{}, - Converter: &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{}, - Repository: repository, - } - + repository.SetMissingHeadersError(fakes.FakeError) err := transformer.Execute() Expect(err).To(HaveOccurred()) @@ -63,34 +78,18 @@ var _ = Describe("Pit file debt ceiling transformer", func() { }) It("fetches logs for missing headers", func() { - fetcher := &mocks.MockLogFetcher{} - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}, {BlockNumber: 2}}) - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Fetcher: fetcher, - Converter: &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{}, - Repository: repository, - } - + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) - Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{pit_file.PitFileConfig.ContractAddresses, pit_file.PitFileConfig.ContractAddresses})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) + Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{config.ContractAddresses, config.ContractAddresses})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.PitFileDebtCeilingSignature)}})) }) It("returns error if fetcher returns error", func() { - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetcherError(fakes.FakeError) - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Fetcher: fetcher, - Converter: &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{}, - Repository: repository, - } - + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).To(HaveOccurred()) @@ -98,34 +97,17 @@ var _ = Describe("Pit file debt ceiling transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{} - mockRepository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{} - mockRepository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedError(fakes.FakeError) err := transformer.Execute() @@ -134,16 +116,8 @@ var _ = Describe("Pit file debt ceiling transformer", func() { }) It("converts matching logs", func() { - converter := &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileDebtCeilingLog}) - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -152,17 +126,9 @@ var _ = Describe("Pit file debt ceiling transformer", func() { }) It("returns error if converter returns error", func() { - converter := &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{} converter.SetConverterError(fakes.FakeError) - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileDebtCeilingLog}) - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -171,37 +137,20 @@ var _ = Describe("Pit file debt ceiling transformer", func() { }) It("persists pit file model", func() { - converter := &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileDebtCeilingLog}) - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - fakeHeader := core.Header{BlockNumber: 1, Id: 2} - repository.SetMissingHeaders([]core.Header{fakeHeader}) - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) - Expect(repository.PassedModels).To(Equal([]debt_ceiling.PitFileDebtCeilingModel{test_data.PitFileDebtCeilingModel})) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.PitFileDebtCeilingModel})) }) It("returns error if repository returns error for create", func() { - converter := &debt_ceiling_mocks.MockPitFileDebtCeilingConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileDebtCeilingLog}) - repository := &debt_ceiling_mocks.MockPitFileDebtCeilingRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}}) + repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := debt_ceiling.PitFileDebtCeilingTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } err := transformer.Execute() diff --git a/pkg/transformers/pit_file/ilk/config.go b/pkg/transformers/pit_file/ilk/config.go new file mode 100644 index 00000000..20d35bc3 --- /dev/null +++ b/pkg/transformers/pit_file/ilk/config.go @@ -0,0 +1,28 @@ +// 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 ilk + +import ( + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" +) + +var IlkFileConfig = shared.SingleTransformerConfig{ + TransformerName: shared.PitFileIlkLabel, + ContractAddresses: []string{shared.PitContractAddress}, + ContractAbi: shared.PitABI, + Topic: shared.PitFileIlkSignature, + StartingBlockNumber: 0, + EndingBlockNumber: 10000000, +} diff --git a/pkg/transformers/pit_file/ilk/converter.go b/pkg/transformers/pit_file/ilk/converter.go index 94777525..823d7823 100644 --- a/pkg/transformers/pit_file/ilk/converter.go +++ b/pkg/transformers/pit_file/ilk/converter.go @@ -24,14 +24,10 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]PitFileIlkModel, error) -} - type PitFileIlkConverter struct{} -func (PitFileIlkConverter) ToModels(ethLogs []types.Log) ([]PitFileIlkModel, error) { - var models []PitFileIlkModel +func (PitFileIlkConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { diff --git a/pkg/transformers/pit_file/ilk/converter_test.go b/pkg/transformers/pit_file/ilk/converter_test.go index 6dba9b9b..8ddfa4e4 100644 --- a/pkg/transformers/pit_file/ilk/converter_test.go +++ b/pkg/transformers/pit_file/ilk/converter_test.go @@ -54,6 +54,6 @@ var _ = Describe("Pit file ilk converter", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(models)).To(Equal(1)) - Expect(models[0]).To(Equal(test_data.PitFileIlkModel)) + Expect(models[0].(ilk.PitFileIlkModel)).To(Equal(test_data.PitFileIlkModel)) }) }) diff --git a/pkg/transformers/pit_file/ilk/repository.go b/pkg/transformers/pit_file/ilk/repository.go index 68ac396b..79cc6576 100644 --- a/pkg/transformers/pit_file/ilk/repository.go +++ b/pkg/transformers/pit_file/ilk/repository.go @@ -15,36 +15,32 @@ package ilk import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerID int64, models []PitFileIlkModel) error - MarkHeaderChecked(headerID int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type PitFileIlkRepository struct { db *postgres.DB } -func NewPitFileIlkRepository(db *postgres.DB) PitFileIlkRepository { - return PitFileIlkRepository{ - db: db, - } -} - -func (repository PitFileIlkRepository) Create(headerID int64, models []PitFileIlkModel) error { +func (repository PitFileIlkRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } + for _, model := range models { + pitFileIlk, ok := model.(PitFileIlkModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, PitFileIlkModel{}) + } + _, err = tx.Exec( `INSERT into maker.pit_file_ilk (header_id, ilk, what, data, tx_idx, raw_log) VALUES($1, $2, $3, $4::NUMERIC, $5, $6)`, - headerID, model.Ilk, model.What, model.Data, model.TransactionIndex, model.Raw, + headerID, pitFileIlk.Ilk, pitFileIlk.What, pitFileIlk.Data, pitFileIlk.TransactionIndex, pitFileIlk.Raw, ) if err != nil { tx.Rollback() @@ -75,14 +71,18 @@ func (repository PitFileIlkRepository) MissingHeaders(startingBlockNumber, endin err := repository.db.Select( &result, `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id + LEFT JOIN checked_headers on headers.id = header_id WHERE (header_id ISNULL OR pit_file_ilk_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, + AND headers.block_number >= $1 + AND headers.block_number <= $2 + AND headers.eth_node_fingerprint = $3`, startingBlockNumber, endingBlockNumber, repository.db.Node.ID, ) return result, err } + +func (repository *PitFileIlkRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/pit_file/ilk/repository_test.go b/pkg/transformers/pit_file/ilk/repository_test.go index feaf9dcd..db7f127d 100644 --- a/pkg/transformers/pit_file/ilk/repository_test.go +++ b/pkg/transformers/pit_file/ilk/repository_test.go @@ -16,6 +16,7 @@ package ilk_test import ( "database/sql" + "math/rand" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -33,7 +34,7 @@ import ( var _ = Describe("Pit file ilk repository", func() { var ( db *postgres.DB - pitFileRepository ilk.Repository + pitFileRepository ilk.PitFileIlkRepository err error headerRepository datastore.HeaderRepository ) @@ -42,7 +43,8 @@ var _ = Describe("Pit file ilk repository", func() { db = test_config.NewTestDB(core.Node{}) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - pitFileRepository = ilk.NewPitFileIlkRepository(db) + pitFileRepository = ilk.PitFileIlkRepository{} + pitFileRepository.SetDB(db) }) Describe("Create", func() { @@ -52,7 +54,7 @@ var _ = Describe("Pit file ilk repository", func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = pitFileRepository.Create(headerID, []ilk.PitFileIlkModel{test_data.PitFileIlkModel}) + err = pitFileRepository.Create(headerID, []interface{}{test_data.PitFileIlkModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -75,7 +77,7 @@ var _ = Describe("Pit file ilk repository", func() { }) It("does not duplicate pit file ilk events", func() { - err = pitFileRepository.Create(headerID, []ilk.PitFileIlkModel{test_data.PitFileIlkModel}) + err = pitFileRepository.Create(headerID, []interface{}{test_data.PitFileIlkModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) @@ -90,6 +92,12 @@ var _ = Describe("Pit file ilk repository", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(sql.ErrNoRows)) }) + + It("Returns an error if model is of wrong type", func() { + err = pitFileRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -130,7 +138,7 @@ var _ = Describe("Pit file ilk repository", func() { ) BeforeEach(func() { - startingBlock = GinkgoRandomSeed() + startingBlock = rand.Int63() pitFileBlock = startingBlock + 1 endingBlock = startingBlock + 2 @@ -176,7 +184,9 @@ var _ = Describe("Pit file ilk repository", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - pitFileRepositoryTwo := ilk.NewPitFileIlkRepository(dbTwo) + + pitFileRepositoryTwo := ilk.PitFileIlkRepository{} + pitFileRepositoryTwo.SetDB(dbTwo) err := pitFileRepository.MarkHeaderChecked(headerIDs[0]) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/pit_file/ilk/transformer.go b/pkg/transformers/pit_file/ilk/transformer.go deleted file mode 100644 index 2318dca0..00000000 --- a/pkg/transformers/pit_file/ilk/transformer.go +++ /dev/null @@ -1,79 +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 ilk - -import ( - "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/pit_file" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -) - -type PitFileIlkTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -type PitFileIlkTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer PitFileIlkTransformerInitializer) NewPitFileIlkTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := PitFileIlkConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewPitFileIlkRepository(db) - return PitFileIlkTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -func (transformer PitFileIlkTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - log.Printf("Fetching pit file ilk event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.PitFileIlkSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(pit_file.PitFileConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - if len(matchingLogs) < 1 { - err = transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - models, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - err = transformer.Repository.Create(header.Id, models) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/pit_file/ilk/transformer_test.go b/pkg/transformers/pit_file/ilk/transformer_test.go index 2b6cf806..4a19c457 100644 --- a/pkg/transformers/pit_file/ilk/transformer_test.go +++ b/pkg/transformers/pit_file/ilk/transformer_test.go @@ -19,42 +19,58 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" - pit_file_ilk_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/pit_file/ilk" + ilk_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/pit_file/ilk" ) var _ = Describe("Pit file ilk transformer", func() { - It("gets missing headers for block numbers specified in config", func() { - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - transformer := ilk.PitFileIlkTransformer{ - Config: pit_file.PitFileConfig, - Fetcher: &mocks.MockLogFetcher{}, - Converter: &pit_file_ilk_mocks.MockPitFileIlkConverter{}, - Repository: repository, - } + var ( + config = ilk.IlkFileConfig + fetcher mocks.MockLogFetcher + converter ilk_mocks.MockPitFileIlkConverter + repository ilk_mocks.MockPitFileIlkRepository + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) + BeforeEach(func() { + fetcher = mocks.MockLogFetcher{} + converter = ilk_mocks.MockPitFileIlkConverter{} + repository = ilk_mocks.MockPitFileIlkRepository{} + headerOne = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + headerTwo = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + transformer = factories.Transformer{ + Config: config, + Converter: &converter, + Repository: &repository, + Fetcher: &fetcher, + }.NewTransformer(nil, nil) + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedStartingBlockNumber).To(Equal(pit_file.PitFileConfig.StartingBlockNumber)) - Expect(repository.PassedEndingBlockNumber).To(Equal(pit_file.PitFileConfig.EndingBlockNumber)) + Expect(repository.PassedStartingBlockNumber).To(Equal(config.StartingBlockNumber)) + Expect(repository.PassedEndingBlockNumber).To(Equal(config.EndingBlockNumber)) }) It("returns error if repository returns error for missing headers", func() { - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - repository.SetMissingHeadersErr(fakes.FakeError) - transformer := ilk.PitFileIlkTransformer{ - Fetcher: &mocks.MockLogFetcher{}, - Converter: &pit_file_ilk_mocks.MockPitFileIlkConverter{}, - Repository: repository, - } + repository.SetMissingHeadersError(fakes.FakeError) err := transformer.Execute() @@ -63,33 +79,19 @@ var _ = Describe("Pit file ilk transformer", func() { }) It("fetches logs for missing headers", func() { - fetcher := &mocks.MockLogFetcher{} - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}, {BlockNumber: 2}}) - transformer := ilk.PitFileIlkTransformer{ - Fetcher: fetcher, - Converter: &pit_file_ilk_mocks.MockPitFileIlkConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) - Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{pit_file.PitFileConfig.ContractAddresses, pit_file.PitFileConfig.ContractAddresses})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) + Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{config.ContractAddresses, config.ContractAddresses})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.PitFileIlkSignature)}})) }) It("returns error if fetcher returns error", func() { - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetcherError(fakes.FakeError) - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := ilk.PitFileIlkTransformer{ - Fetcher: fetcher, - Converter: &pit_file_ilk_mocks.MockPitFileIlkConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -98,34 +100,17 @@ var _ = Describe("Pit file ilk transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &pit_file_ilk_mocks.MockPitFileIlkConverter{} - mockRepository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := ilk.PitFileIlkTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &pit_file_ilk_mocks.MockPitFileIlkConverter{} - mockRepository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := ilk.PitFileIlkTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedError(fakes.FakeError) err := transformer.Execute() @@ -134,16 +119,8 @@ var _ = Describe("Pit file ilk transformer", func() { }) It("converts matching logs", func() { - converter := &pit_file_ilk_mocks.MockPitFileIlkConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileIlkLog}) - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := ilk.PitFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -152,17 +129,9 @@ var _ = Describe("Pit file ilk transformer", func() { }) It("returns error if converter returns error", func() { - converter := &pit_file_ilk_mocks.MockPitFileIlkConverter{} converter.SetConverterError(fakes.FakeError) - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileIlkLog}) - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := ilk.PitFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -171,37 +140,20 @@ var _ = Describe("Pit file ilk transformer", func() { }) It("persists pit file model", func() { - converter := &pit_file_ilk_mocks.MockPitFileIlkConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileIlkLog}) - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - fakeHeader := core.Header{BlockNumber: 1, Id: 2} - repository.SetMissingHeaders([]core.Header{fakeHeader}) - transformer := ilk.PitFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) - Expect(repository.PassedModels).To(Equal([]ilk.PitFileIlkModel{test_data.PitFileIlkModel})) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.PitFileIlkModel})) }) It("returns error if repository returns error for create", func() { - converter := &pit_file_ilk_mocks.MockPitFileIlkConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileIlkLog}) - repository := &pit_file_ilk_mocks.MockPitFileIlkRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}}) + repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := ilk.PitFileIlkTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } err := transformer.Execute() diff --git a/pkg/transformers/pit_file/stability_fee/config.go b/pkg/transformers/pit_file/stability_fee/config.go new file mode 100644 index 00000000..01848543 --- /dev/null +++ b/pkg/transformers/pit_file/stability_fee/config.go @@ -0,0 +1,28 @@ +// 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 stability_fee + +import ( + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" +) + +var StabilityFeeFileConfig = shared.SingleTransformerConfig{ + TransformerName: shared.PitFileStabilityFeeLabel, + ContractAddresses: []string{shared.PitContractAddress}, + ContractAbi: shared.PitABI, + Topic: shared.PitFileStabilityFeeSignature, + StartingBlockNumber: 0, + EndingBlockNumber: 10000000, +} diff --git a/pkg/transformers/pit_file/stability_fee/converter.go b/pkg/transformers/pit_file/stability_fee/converter.go index 27d20155..6f47ec51 100644 --- a/pkg/transformers/pit_file/stability_fee/converter.go +++ b/pkg/transformers/pit_file/stability_fee/converter.go @@ -23,14 +23,10 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]PitFileStabilityFeeModel, error) -} - type PitFileStabilityFeeConverter struct{} -func (PitFileStabilityFeeConverter) ToModels(ethLogs []types.Log) ([]PitFileStabilityFeeModel, error) { - var models []PitFileStabilityFeeModel +func (PitFileStabilityFeeConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { diff --git a/pkg/transformers/pit_file/stability_fee/repository.go b/pkg/transformers/pit_file/stability_fee/repository.go index 6942512f..f0421175 100644 --- a/pkg/transformers/pit_file/stability_fee/repository.go +++ b/pkg/transformers/pit_file/stability_fee/repository.go @@ -15,50 +15,50 @@ package stability_fee import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerID int64, models []PitFileStabilityFeeModel) error - MarkHeaderChecked(headerID int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type PitFileStabilityFeeRepository struct { db *postgres.DB } -func NewPitFileStabilityFeeRepository(db *postgres.DB) PitFileStabilityFeeRepository { - return PitFileStabilityFeeRepository{ - db: db, - } -} - -func (repository PitFileStabilityFeeRepository) Create(headerID int64, models []PitFileStabilityFeeModel) error { +func (repository PitFileStabilityFeeRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } + for _, model := range models { + pitFileSF, ok := model.(PitFileStabilityFeeModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, PitFileStabilityFeeModel{}) + } + _, err = tx.Exec( `INSERT into maker.pit_file_stability_fee (header_id, what, data, tx_idx, raw_log) VALUES($1, $2, $3, $4, $5)`, - headerID, model.What, model.Data, model.TransactionIndex, model.Raw, + headerID, pitFileSF.What, pitFileSF.Data, pitFileSF.TransactionIndex, pitFileSF.Raw, ) + if err != nil { tx.Rollback() return err } } + _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, pit_file_stability_fee_checked) VALUES ($1, $2) ON CONFLICT (header_id) DO UPDATE SET pit_file_stability_fee_checked = $2`, headerID, true) + if err != nil { tx.Rollback() return err } + return tx.Commit() } @@ -86,3 +86,7 @@ func (repository PitFileStabilityFeeRepository) MissingHeaders(startingBlockNumb ) return result, err } + +func (repository *PitFileStabilityFeeRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/pit_file/stability_fee/repository_test.go b/pkg/transformers/pit_file/stability_fee/repository_test.go index 499f71fa..3fc01692 100644 --- a/pkg/transformers/pit_file/stability_fee/repository_test.go +++ b/pkg/transformers/pit_file/stability_fee/repository_test.go @@ -16,6 +16,7 @@ package stability_fee_test import ( "database/sql" + "math/rand" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -32,17 +33,18 @@ import ( var _ = Describe("Pit file stability fee repository", func() { var ( - db *postgres.DB - pitFileRepository stability_fee.Repository - err error - headerRepository datastore.HeaderRepository + db *postgres.DB + pitFileStabilityFeeRepository stability_fee.PitFileStabilityFeeRepository + err error + headerRepository datastore.HeaderRepository ) BeforeEach(func() { db = test_config.NewTestDB(core.Node{}) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - pitFileRepository = stability_fee.NewPitFileStabilityFeeRepository(db) + pitFileStabilityFeeRepository = stability_fee.PitFileStabilityFeeRepository{} + pitFileStabilityFeeRepository.SetDB(db) }) Describe("Create", func() { @@ -52,7 +54,7 @@ var _ = Describe("Pit file stability fee repository", func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = pitFileRepository.Create(headerID, []stability_fee.PitFileStabilityFeeModel{test_data.PitFileStabilityFeeModel}) + err = pitFileStabilityFeeRepository.Create(headerID, []interface{}{test_data.PitFileStabilityFeeModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -74,7 +76,7 @@ var _ = Describe("Pit file stability fee repository", func() { }) It("does not duplicate pit file events", func() { - err = pitFileRepository.Create(headerID, []stability_fee.PitFileStabilityFeeModel{test_data.PitFileStabilityFeeModel}) + err = pitFileStabilityFeeRepository.Create(headerID, []interface{}{test_data.PitFileStabilityFeeModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) @@ -89,6 +91,12 @@ var _ = Describe("Pit file stability fee repository", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(sql.ErrNoRows)) }) + + It("Returns an error if model is of wrong type", func() { + err = pitFileStabilityFeeRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -100,7 +108,7 @@ var _ = Describe("Pit file stability fee repository", func() { }) It("creates a row for a new headerID", func() { - err = pitFileRepository.MarkHeaderChecked(headerID) + err = pitFileStabilityFeeRepository.MarkHeaderChecked(headerID) Expect(err).NotTo(HaveOccurred()) var headerChecked bool @@ -112,7 +120,7 @@ var _ = Describe("Pit file stability fee repository", func() { It("updates row when headerID already exists", func() { _, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerID) - err = pitFileRepository.MarkHeaderChecked(headerID) + err = pitFileStabilityFeeRepository.MarkHeaderChecked(headerID) Expect(err).NotTo(HaveOccurred()) var headerChecked bool @@ -129,7 +137,7 @@ var _ = Describe("Pit file stability fee repository", func() { ) BeforeEach(func() { - startingBlock = GinkgoRandomSeed() + startingBlock = rand.Int63() pitFileBlock = startingBlock + 1 endingBlock = startingBlock + 2 @@ -144,10 +152,10 @@ var _ = Describe("Pit file stability fee repository", func() { }) It("returns headers that haven't been checked", func() { - err := pitFileRepository.MarkHeaderChecked(headerIDs[1]) + err = pitFileStabilityFeeRepository.MarkHeaderChecked(headerIDs[1]) Expect(err).NotTo(HaveOccurred()) - headers, err := pitFileRepository.MissingHeaders(startingBlock, endingBlock) + headers, err := pitFileStabilityFeeRepository.MissingHeaders(startingBlock, endingBlock) Expect(err).NotTo(HaveOccurred()) Expect(len(headers)).To(Equal(2)) @@ -156,10 +164,10 @@ var _ = Describe("Pit file stability fee repository", func() { }) It("only treats headers as checked if pit file stability fee logs have been checked", func() { - _, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerIDs[1]) + _, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerIDs[1]) Expect(err).NotTo(HaveOccurred()) - headers, err := pitFileRepository.MissingHeaders(startingBlock, endingBlock) + headers, err := pitFileStabilityFeeRepository.MissingHeaders(startingBlock, endingBlock) Expect(err).NotTo(HaveOccurred()) Expect(len(headers)).To(Equal(3)) @@ -175,11 +183,13 @@ var _ = Describe("Pit file stability fee repository", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - pitFileRepositoryTwo := stability_fee.NewPitFileStabilityFeeRepository(dbTwo) - err := pitFileRepository.MarkHeaderChecked(headerIDs[0]) + + pitFileRepositoryTwo := stability_fee.PitFileStabilityFeeRepository{} + pitFileRepositoryTwo.SetDB(dbTwo) + err = pitFileStabilityFeeRepository.MarkHeaderChecked(headerIDs[0]) Expect(err).NotTo(HaveOccurred()) - nodeOneMissingHeaders, err := pitFileRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) + nodeOneMissingHeaders, err := pitFileStabilityFeeRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) Expect(err).NotTo(HaveOccurred()) Expect(len(nodeOneMissingHeaders)).To(Equal(len(blockNumbers) - 1)) diff --git a/pkg/transformers/pit_file/stability_fee/transformer.go b/pkg/transformers/pit_file/stability_fee/transformer.go deleted file mode 100644 index 781c223e..00000000 --- a/pkg/transformers/pit_file/stability_fee/transformer.go +++ /dev/null @@ -1,79 +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 stability_fee - -import ( - "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/pit_file" - "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -) - -type PitFileStabilityFeeTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -type PitFileStabilityFeeTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer PitFileStabilityFeeTransformerInitializer) NewPitFileStabilityFeeTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := PitFileStabilityFeeConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewPitFileStabilityFeeRepository(db) - return PitFileStabilityFeeTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -func (transformer PitFileStabilityFeeTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - log.Printf("Fetching pit file stability fee event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.PitFileStabilityFeeSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(pit_file.PitFileConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - if len(matchingLogs) < 1 { - err = transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - models, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - err = transformer.Repository.Create(header.Id, models) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/pit_file/stability_fee/transformer_test.go b/pkg/transformers/pit_file/stability_fee/transformer_test.go index b2464af7..ffab7ced 100644 --- a/pkg/transformers/pit_file/stability_fee/transformer_test.go +++ b/pkg/transformers/pit_file/stability_fee/transformer_test.go @@ -19,11 +19,12 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" @@ -31,31 +32,45 @@ import ( ) var _ = Describe("Pit file stability fee transformer", func() { - It("gets missing headers for block numbers specified in config", func() { - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Config: pit_file.PitFileConfig, - Fetcher: &mocks.MockLogFetcher{}, - Converter: &stability_fee_mocks.MockPitFileStabilityFeeConverter{}, - Repository: repository, - } + var ( + config = stability_fee.StabilityFeeFileConfig + fetcher mocks.MockLogFetcher + converter stability_fee_mocks.MockPitFileStabilityFeeConverter + repository stability_fee_mocks.MockPitFileStabilityFeeRepository + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) + BeforeEach(func() { + fetcher = mocks.MockLogFetcher{} + converter = stability_fee_mocks.MockPitFileStabilityFeeConverter{} + repository = stability_fee_mocks.MockPitFileStabilityFeeRepository{} + transformer = factories.Transformer{ + Config: config, + Fetcher: &fetcher, + Converter: &converter, + Repository: &repository, + }.NewTransformer(nil, nil) + headerOne = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + headerTwo = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedStartingBlockNumber).To(Equal(pit_file.PitFileConfig.StartingBlockNumber)) - Expect(repository.PassedEndingBlockNumber).To(Equal(pit_file.PitFileConfig.EndingBlockNumber)) + Expect(repository.PassedStartingBlockNumber).To(Equal(config.StartingBlockNumber)) + Expect(repository.PassedEndingBlockNumber).To(Equal(config.EndingBlockNumber)) }) It("returns error if repository returns error for missing headers", func() { - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} repository.SetMissingHeadersErr(fakes.FakeError) - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Fetcher: &mocks.MockLogFetcher{}, - Converter: &stability_fee_mocks.MockPitFileStabilityFeeConverter{}, - Repository: repository, - } - err := transformer.Execute() Expect(err).To(HaveOccurred()) @@ -63,33 +78,19 @@ var _ = Describe("Pit file stability fee transformer", func() { }) It("fetches logs for missing headers", func() { - fetcher := &mocks.MockLogFetcher{} - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}, {BlockNumber: 2}}) - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Fetcher: fetcher, - Converter: &stability_fee_mocks.MockPitFileStabilityFeeConverter{}, - Repository: repository, - } - + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) - Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{pit_file.PitFileConfig.ContractAddresses, pit_file.PitFileConfig.ContractAddresses})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) + Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{ + config.ContractAddresses, config.ContractAddresses})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.PitFileStabilityFeeSignature)}})) }) It("returns error if fetcher returns error", func() { - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetcherError(fakes.FakeError) - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Fetcher: fetcher, - Converter: &stability_fee_mocks.MockPitFileStabilityFeeConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -98,34 +99,17 @@ var _ = Describe("Pit file stability fee transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &stability_fee_mocks.MockPitFileStabilityFeeConverter{} - mockRepository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &stability_fee_mocks.MockPitFileStabilityFeeConverter{} - mockRepository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedErr(fakes.FakeError) err := transformer.Execute() @@ -134,16 +118,8 @@ var _ = Describe("Pit file stability fee transformer", func() { }) It("converts matching logs", func() { - converter := &stability_fee_mocks.MockPitFileStabilityFeeConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileStabilityFeeLog}) - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -152,17 +128,9 @@ var _ = Describe("Pit file stability fee transformer", func() { }) It("returns error if converter returns error", func() { - converter := &stability_fee_mocks.MockPitFileStabilityFeeConverter{} converter.SetConverterError(fakes.FakeError) - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileStabilityFeeLog}) - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -171,37 +139,20 @@ var _ = Describe("Pit file stability fee transformer", func() { }) It("persists pit file model", func() { - converter := &stability_fee_mocks.MockPitFileStabilityFeeConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileStabilityFeeLog}) - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - fakeHeader := core.Header{BlockNumber: 1, Id: 2} - repository.SetMissingHeaders([]core.Header{fakeHeader}) - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) - Expect(repository.PassedModels).To(Equal([]stability_fee.PitFileStabilityFeeModel{test_data.PitFileStabilityFeeModel})) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.PitFileStabilityFeeModel})) }) It("returns error if repository returns error for create", func() { - converter := &stability_fee_mocks.MockPitFileStabilityFeeConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthPitFileStabilityFeeLog}) - repository := &stability_fee_mocks.MockPitFileStabilityFeeRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}}) + repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := stability_fee.PitFileStabilityFeeTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } err := transformer.Execute() diff --git a/pkg/transformers/shared/constants.go b/pkg/transformers/shared/constants.go index 6b3c2180..463deee1 100644 --- a/pkg/transformers/shared/constants.go +++ b/pkg/transformers/shared/constants.go @@ -102,4 +102,32 @@ var ( VatTollSignature = GetLogNoteSignature(vatTollMethod) VatTuneSignature = GetLogNoteSignature(vatTuneMethod) VatFluxSignature = GetLogNoteSignature(vatFluxMethod) + + BiteLabel = "bite" + DealLabel = "deal" + CatFileChopLumpLabel = "catFileChopLump" + CatFileFlipLabel = "catFileFlip" + CatFilePitVowLabel = "catFilePitVow" + DentLabel = "dent" + DripDripLabel = "dripDrip" + DripFileIlkLabel = "dripFileIlk" + DripFileRepoLabel = "dripFileRepo" + DripFileVowLabel = "dripFileVow" + FlipKickLabel = "flipKick" + FlopKickLabel = "flopKick" + FrobLabel = "frob" + PitFileDebtCeilingLabel = "pitFileDebtCeiling" + PitFileIlkLabel = "pitFileIlk" + PitFileStabilityFeeLabel = "pitFileStabilityFee" + PriceFeedLabel = "priceFeed" + TendLabel = "tend" + VatHealLabel = "vatHeal" + VatGrabLabel = "vatGrab" + VatInitLabel = "vatInit" + VatMoveLabel = "vatMove" + VatFoldLabel = "vatFold" + VatSlipLabel = "vatSlip" + VatTollLabel = "vatToll" + VatTuneLabel = "vatTune" + VatFluxLabel = "vatFlux" ) diff --git a/pkg/transformers/shared/log_fetcher.go b/pkg/transformers/shared/log_fetcher.go index a42a18ff..46d4f3dc 100644 --- a/pkg/transformers/shared/log_fetcher.go +++ b/pkg/transformers/shared/log_fetcher.go @@ -28,10 +28,19 @@ type LogFetcher interface { FetchLogs(contractAddresses []string, topics [][]common.Hash, blockNumber int64) ([]types.Log, error) } +type SettableLogFetcher interface { + LogFetcher + SetBC(bc core.BlockChain) +} + type Fetcher struct { blockChain core.BlockChain } +func (fetcher *Fetcher) SetBC(bc core.BlockChain) { + fetcher.blockChain = bc +} + func NewFetcher(blockchain core.BlockChain) Fetcher { return Fetcher{ blockChain: blockchain, diff --git a/pkg/transformers/shared/transformer.go b/pkg/transformers/shared/transformer.go index 1b07026e..a647e9a7 100644 --- a/pkg/transformers/shared/transformer.go +++ b/pkg/transformers/shared/transformer.go @@ -28,9 +28,19 @@ type Transformer interface { type TransformerInitializer func(db *postgres.DB, blockChain core.BlockChain) Transformer type TransformerConfig struct { + TransformerName string ContractAddresses []string ContractAbi string - Topics []string + Topics []string // TODO Change this to single topic + StartingBlockNumber int64 + EndingBlockNumber int64 +} + +type SingleTransformerConfig struct { + TransformerName string + ContractAddresses []string + ContractAbi string + Topic string StartingBlockNumber int64 EndingBlockNumber int64 } diff --git a/pkg/transformers/tend/config.go b/pkg/transformers/tend/config.go index 7ec52f9b..d4911e45 100644 --- a/pkg/transformers/tend/config.go +++ b/pkg/transformers/tend/config.go @@ -16,10 +16,11 @@ package tend import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" -var TendConfig = shared.TransformerConfig{ +var TendConfig = shared.SingleTransformerConfig{ + TransformerName: shared.TendLabel, ContractAddresses: []string{shared.FlipperContractAddress}, ContractAbi: shared.FlipperABI, - Topics: []string{shared.TendFunctionSignature}, + Topic: shared.TendFunctionSignature, StartingBlockNumber: 0, EndingBlockNumber: 10000000, } diff --git a/pkg/transformers/tend/converter.go b/pkg/transformers/tend/converter.go index dd989d08..52ace3c1 100644 --- a/pkg/transformers/tend/converter.go +++ b/pkg/transformers/tend/converter.go @@ -23,17 +23,9 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]TendModel, error) -} - type TendConverter struct{} -func NewTendConverter() TendConverter { - return TendConverter{} -} - -func (c TendConverter) ToModels(ethLogs []types.Log) (results []TendModel, err error) { +func (TendConverter) ToModels(ethLogs []types.Log) (results []interface{}, err error) { for _, ethLog := range ethLogs { err := validateLog(ethLog) if err != nil { diff --git a/pkg/transformers/tend/converter_test.go b/pkg/transformers/tend/converter_test.go index db53220d..ec07fec3 100644 --- a/pkg/transformers/tend/converter_test.go +++ b/pkg/transformers/tend/converter_test.go @@ -28,7 +28,7 @@ var _ = Describe("Tend TendConverter", func() { var converter tend.TendConverter BeforeEach(func() { - converter = tend.NewTendConverter() + converter = tend.TendConverter{} }) Describe("ToModels", func() { diff --git a/pkg/transformers/tend/repository.go b/pkg/transformers/tend/repository.go index 84cf2d22..de1ef581 100644 --- a/pkg/transformers/tend/repository.go +++ b/pkg/transformers/tend/repository.go @@ -15,35 +15,34 @@ package tend import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerId int64, tends []TendModel) error - MarkHeaderChecked(headerId int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type TendRepository struct { - DB *postgres.DB + db *postgres.DB } -func NewTendRepository(db *postgres.DB) TendRepository { - return TendRepository{DB: db} -} - -func (r TendRepository) Create(headerId int64, tends []TendModel) error { - tx, err := r.DB.Begin() +func (repository TendRepository) Create(headerId int64, models []interface{}) error { + tx, err := repository.db.Begin() if err != nil { return err } - for _, tend := range tends { + + for _, model := range models { + tend, ok := model.(TendModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, TendModel{}) + } + _, err = tx.Exec( `INSERT into maker.tend (header_id, bid_id, lot, bid, guy, tic, tx_idx, raw_log) - VALUES($1, $2, $3, $4, $5, $6, $7, $8)`, + VALUES($1, $2, $3, $4, $5, $6, $7, $8)`, headerId, tend.BidId, tend.Lot, tend.Bid, tend.Guy, tend.Tic, tend.TransactionIndex, tend.Raw, ) + if err != nil { tx.Rollback() return err @@ -53,6 +52,7 @@ func (r TendRepository) Create(headerId int64, tends []TendModel) error { VALUES ($1, $2) ON CONFLICT (header_id) DO UPDATE SET tend_checked = $2`, headerId, true) + if err != nil { tx.Rollback() return err @@ -60,28 +60,32 @@ func (r TendRepository) Create(headerId int64, tends []TendModel) error { return tx.Commit() } -func (r TendRepository) MarkHeaderChecked(headerId int64) error { - _, err := r.DB.Exec(`INSERT INTO public.checked_headers (header_id, tend_checked) +func (repository TendRepository) MarkHeaderChecked(headerId int64) error { + _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, tend_checked) VALUES ($1, $2) ON CONFLICT (header_id) DO UPDATE SET tend_checked = $2`, headerId, true) return err } -func (r TendRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { +func (repository TendRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { var result []core.Header - err := r.DB.Select( + err := repository.db.Select( &result, `SELECT headers.id, headers.block_number FROM headers - LEFT JOIN checked_headers on headers.id = header_id + LEFT JOIN checked_headers on headers.id = header_id WHERE (header_id ISNULL OR tend_checked IS FALSE) - AND headers.block_number >= $1 - AND headers.block_number <= $2 - AND headers.eth_node_fingerprint = $3`, + AND headers.block_number >= $1 + AND headers.block_number <= $2 + AND headers.eth_node_fingerprint = $3`, startingBlockNumber, endingBlockNumber, - r.DB.Node.ID, + repository.db.Node.ID, ) return result, err } + +func (repository *TendRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/tend/repository_test.go b/pkg/transformers/tend/repository_test.go index 943c96cc..d9d2e7a3 100644 --- a/pkg/transformers/tend/repository_test.go +++ b/pkg/transformers/tend/repository_test.go @@ -17,6 +17,7 @@ package tend_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" @@ -32,6 +33,7 @@ var _ = Describe("TendRepository", func() { db *postgres.DB tendRepository tend.TendRepository headerRepository repositories.HeaderRepository + headerId int64 err error ) @@ -40,17 +42,16 @@ var _ = Describe("TendRepository", func() { db = test_config.NewTestDB(node) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - tendRepository = tend.NewTendRepository(db) + tendRepository = tend.TendRepository{} + tendRepository.SetDB(db) }) Describe("Create", func() { - var headerId int64 - BeforeEach(func() { headerId, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err := tendRepository.Create(headerId, []tend.TendModel{test_data.TendModel}) + err = tendRepository.Create(headerId, []interface{}{test_data.TendModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -81,8 +82,7 @@ var _ = Describe("TendRepository", func() { }) It("returns an error if inserting a tend record fails", func() { - err = tendRepository.Create(headerId, []tend.TendModel{test_data.TendModel}) - + err = tendRepository.Create(headerId, []interface{}{test_data.TendModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) }) @@ -100,11 +100,15 @@ var _ = Describe("TendRepository", func() { Expect(err).NotTo(HaveOccurred()) Expect(count).To(Equal(0)) }) + + It("Returns an error if model is of wrong type", func() { + err = tendRepository.Create(headerId, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { - var headerId int64 - BeforeEach(func() { headerId, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) @@ -140,7 +144,7 @@ var _ = Describe("TendRepository", func() { ) BeforeEach(func() { - tendBlock = GinkgoRandomSeed() + tendBlock = rand.Int63() startingBlock = tendBlock - 1 endingBlock = tendBlock + 1 outOfRangeBlock = tendBlock + 2 @@ -182,7 +186,8 @@ var _ = Describe("TendRepository", func() { node2 := core.Node{} db2 := test_config.NewTestDB(node2) headerRepository2 := repositories.NewHeaderRepository(db2) - tendRepository2 := tend.NewTendRepository(db2) + tendRepository2 := tend.TendRepository{} + tendRepository2.SetDB(db2) for _, number := range []int64{startingBlock, tendBlock, endingBlock} { headerRepository2.CreateOrUpdateHeader(fakes.GetFakeHeader(number)) diff --git a/pkg/transformers/tend/transformer.go b/pkg/transformers/tend/transformer.go deleted file mode 100644 index ea8ce4b8..00000000 --- a/pkg/transformers/tend/transformer.go +++ /dev/null @@ -1,88 +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 tend - -import ( - "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 TendTransformer struct { - Repository Repository - Fetcher shared.LogFetcher - Converter Converter - Config shared.TransformerConfig -} - -type TendTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (i TendTransformerInitializer) NewTendTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := NewTendConverter() - fetcher := shared.NewFetcher(blockChain) - repository := NewTendRepository(db) - return TendTransformer{ - Fetcher: fetcher, - Repository: repository, - Converter: converter, - Config: i.Config, - } -} - -func (t TendTransformer) Execute() error { - config := t.Config - topics := [][]common.Hash{{common.HexToHash(shared.TendFunctionSignature)}} - - missingHeaders, err := t.Repository.MissingHeaders(config.StartingBlockNumber, config.EndingBlockNumber) - if err != nil { - log.Println("Error fetching missing headers:", err) - return err - } - - log.Printf("Fetching tend event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - ethLogs, err := t.Fetcher.FetchLogs(config.ContractAddresses, topics, header.BlockNumber) - if err != nil { - log.Println("Error fetching matching logs:", err) - return err - } - if len(ethLogs) < 1 { - err := t.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - - models, err := t.Converter.ToModels(ethLogs) - if err != nil { - log.Println("Error converting logs:", err) - return err - } - - err = t.Repository.Create(header.Id, models) - if err != nil { - log.Println("Error persisting tend record:", err) - return err - } - } - - return nil -} diff --git a/pkg/transformers/tend/transformer_test.go b/pkg/transformers/tend/transformer_test.go index 57181cb3..1f55a832 100644 --- a/pkg/transformers/tend/transformer_test.go +++ b/pkg/transformers/tend/transformer_test.go @@ -15,6 +15,7 @@ package tend_test import ( + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "math/rand" "github.com/ethereum/go-ethereum/common" @@ -32,24 +33,33 @@ import ( ) var _ = Describe("Tend Transformer", func() { - var repository tend_mocks.MockTendRepository - var fetcher mocks.MockLogFetcher - var converter tend_mocks.MockTendConverter - var transformer tend.TendTransformer - var blockNumber1 = rand.Int63() - var blockNumber2 = rand.Int63() + var ( + config = tend.TendConfig + converter tend_mocks.MockTendConverter + repository tend_mocks.MockTendRepository + fetcher mocks.MockLogFetcher + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) BeforeEach(func() { + converter = tend_mocks.MockTendConverter{} repository = tend_mocks.MockTendRepository{} fetcher = mocks.MockLogFetcher{} - converter = tend_mocks.MockTendConverter{} - - transformer = tend.TendTransformer{ - Repository: &repository, + headerOne = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + headerTwo = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + transformer = factories.Transformer{ + Config: config, Fetcher: &fetcher, Converter: &converter, - Config: tend.TendConfig, - } + Repository: &repository, + }.NewTransformer(nil, nil) + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) }) It("gets missing headers for blocks in the configured range", func() { @@ -68,12 +78,12 @@ var _ = Describe("Tend Transformer", func() { }) It("fetches eth logs for each missing header", func() { - repository.SetMissingHeaders([]core.Header{{BlockNumber: blockNumber1}, {BlockNumber: blockNumber2}}) + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) expectedTopics := [][]common.Hash{{common.HexToHash(shared.TendFunctionSignature)}} err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{blockNumber1, blockNumber2})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) Expect(fetcher.FetchedTopics).To(Equal(expectedTopics)) Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{tend.TendConfig.ContractAddresses, tend.TendConfig.ContractAddresses})) }) @@ -88,34 +98,17 @@ var _ = Describe("Tend Transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &tend_mocks.MockTendConverter{} - mockRepository := &tend_mocks.MockTendRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := tend.TendTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &tend_mocks.MockTendConverter{} - mockRepository := &tend_mocks.MockTendRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := tend.TendTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedErr(fakes.FakeError) err := transformer.Execute() @@ -124,37 +117,37 @@ var _ = Describe("Tend Transformer", func() { }) It("converts an eth log to a Model", func() { - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) + repository.SetMissingHeaders([]core.Header{headerOne}) fetcher.SetFetchedLogs([]types.Log{test_data.TendLogNote}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(converter.LogsToConvert).To(Equal([]types.Log{test_data.TendLogNote})) + Expect(converter.PassedLogs).To(Equal([]types.Log{test_data.TendLogNote})) }) It("returns an error if converter fails", func() { - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) + repository.SetMissingHeaders([]core.Header{headerOne}) fetcher.SetFetchedLogs([]types.Log{test_data.TendLogNote}) converter.SetConverterError(fakes.FakeError) err := transformer.Execute() + Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(fakes.FakeError)) }) It("persists the tend record", func() { - headerId := int64(1) - repository.SetMissingHeaders([]core.Header{{BlockNumber: blockNumber1, Id: headerId}}) + repository.SetMissingHeaders([]core.Header{headerOne}) fetcher.SetFetchedLogs([]types.Log{test_data.TendLogNote}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(headerId)) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) Expect(repository.PassedTendModel).To(Equal(test_data.TendModel)) }) It("returns error if persisting tend record fails", func() { - repository.SetMissingHeaders([]core.Header{{BlockNumber: blockNumber1}}) + repository.SetMissingHeaders([]core.Header{headerOne}) fetcher.SetFetchedLogs([]types.Log{test_data.TendLogNote}) repository.SetCreateError(fakes.FakeError) err := transformer.Execute() diff --git a/pkg/transformers/test_data/mocks/drip_file/ilk/converter.go b/pkg/transformers/test_data/mocks/drip_file/ilk/converter.go index 85492371..0ab9ace0 100644 --- a/pkg/transformers/test_data/mocks/drip_file/ilk/converter.go +++ b/pkg/transformers/test_data/mocks/drip_file/ilk/converter.go @@ -16,20 +16,19 @@ package ilk import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) type MockDripFileIlkConverter struct { - converterErr error - PassedLogs []types.Log + converterError error + PassedLogs []types.Log } -func (converter *MockDripFileIlkConverter) ToModels(ethLogs []types.Log) ([]ilk.DripFileIlkModel, error) { +func (converter *MockDripFileIlkConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []ilk.DripFileIlkModel{test_data.DripFileIlkModel}, converter.converterErr + return []interface{}{test_data.DripFileIlkModel}, converter.converterError } func (converter *MockDripFileIlkConverter) SetConverterError(e error) { - converter.converterErr = e + converter.converterError = e } diff --git a/pkg/transformers/test_data/mocks/drip_file/ilk/repository.go b/pkg/transformers/test_data/mocks/drip_file/ilk/repository.go index b76aa85e..3f99a840 100644 --- a/pkg/transformers/test_data/mocks/drip_file/ilk/repository.go +++ b/pkg/transformers/test_data/mocks/drip_file/ilk/repository.go @@ -16,46 +16,47 @@ package ilk import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/ilk" ) type MockDripFileIlkRepository struct { - createErr error - markHeaderCheckedErr error + createError error + markHeaderCheckedError error markHeaderCheckedPassedHeaderID int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error PassedStartingBlockNumber int64 PassedEndingBlockNumber int64 PassedHeaderID int64 - PassedModels []ilk.DripFileIlkModel + PassedModels []interface{} + SetDbCalled bool } -func (repository *MockDripFileIlkRepository) Create(headerID int64, models []ilk.DripFileIlkModel) error { +func (repository *MockDripFileIlkRepository) Create(headerID int64, models []interface{}) error { repository.PassedHeaderID = headerID repository.PassedModels = models - return repository.createErr + return repository.createError } func (repository *MockDripFileIlkRepository) MarkHeaderChecked(headerID int64) error { repository.markHeaderCheckedPassedHeaderID = headerID - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } func (repository *MockDripFileIlkRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } -func (repository *MockDripFileIlkRepository) SetMarkHeaderCheckedErr(e error) { - repository.markHeaderCheckedErr = e +func (repository *MockDripFileIlkRepository) SetMarkHeaderCheckedError(e error) { + repository.markHeaderCheckedError = e } -func (repository *MockDripFileIlkRepository) SetMissingHeadersErr(e error) { - repository.missingHeadersErr = e +func (repository *MockDripFileIlkRepository) SetMissingHeadersError(e error) { + repository.missingHeadersError = e } func (repository *MockDripFileIlkRepository) SetMissingHeaders(headers []core.Header) { @@ -63,8 +64,12 @@ func (repository *MockDripFileIlkRepository) SetMissingHeaders(headers []core.He } func (repository *MockDripFileIlkRepository) SetCreateError(e error) { - repository.createErr = e + repository.createError = e } func (repository *MockDripFileIlkRepository) AssertMarkHeaderCheckedCalledWith(i int64) { Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(i)) } + +func (repository *MockDripFileIlkRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/drip_file/repo/converter.go b/pkg/transformers/test_data/mocks/drip_file/repo/converter.go index 0dbe80d0..528fef56 100644 --- a/pkg/transformers/test_data/mocks/drip_file/repo/converter.go +++ b/pkg/transformers/test_data/mocks/drip_file/repo/converter.go @@ -16,20 +16,19 @@ package repo import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/repo" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) type MockDripFileRepoConverter struct { - converterErr error - PassedLogs []types.Log + converterError error + PassedLogs []types.Log } -func (converter *MockDripFileRepoConverter) ToModels(ethLogs []types.Log) ([]repo.DripFileRepoModel, error) { +func (converter *MockDripFileRepoConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []repo.DripFileRepoModel{test_data.DripFileRepoModel}, converter.converterErr + return []interface{}{test_data.DripFileRepoModel}, converter.converterError } func (converter *MockDripFileRepoConverter) SetConverterError(e error) { - converter.converterErr = e + converter.converterError = e } diff --git a/pkg/transformers/test_data/mocks/drip_file/repo/repository.go b/pkg/transformers/test_data/mocks/drip_file/repo/repository.go index be03693a..b1ae32c3 100644 --- a/pkg/transformers/test_data/mocks/drip_file/repo/repository.go +++ b/pkg/transformers/test_data/mocks/drip_file/repo/repository.go @@ -16,46 +16,47 @@ package repo import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/repo" ) type MockDripFileRepoRepository struct { - createErr error - markHeaderCheckedErr error + createError error + markHeaderCheckedError error markHeaderCheckedPassedHeaderID int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error PassedStartingBlockNumber int64 PassedEndingBlockNumber int64 PassedHeaderID int64 - PassedModels []repo.DripFileRepoModel + PassedModels []interface{} + SetDbCalled bool } -func (repository *MockDripFileRepoRepository) Create(headerID int64, models []repo.DripFileRepoModel) error { +func (repository *MockDripFileRepoRepository) Create(headerID int64, models []interface{}) error { repository.PassedHeaderID = headerID repository.PassedModels = models - return repository.createErr + return repository.createError } func (repository *MockDripFileRepoRepository) MarkHeaderChecked(headerID int64) error { repository.markHeaderCheckedPassedHeaderID = headerID - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } func (repository *MockDripFileRepoRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } -func (repository *MockDripFileRepoRepository) SetMarkHeaderCheckedErr(e error) { - repository.markHeaderCheckedErr = e +func (repository *MockDripFileRepoRepository) SetMarkHeaderCheckedError(e error) { + repository.markHeaderCheckedError = e } -func (repository *MockDripFileRepoRepository) SetMissingHeadersErr(e error) { - repository.missingHeadersErr = e +func (repository *MockDripFileRepoRepository) SetMissingHeadersError(e error) { + repository.missingHeadersError = e } func (repository *MockDripFileRepoRepository) SetMissingHeaders(headers []core.Header) { @@ -63,8 +64,13 @@ func (repository *MockDripFileRepoRepository) SetMissingHeaders(headers []core.H } func (repository *MockDripFileRepoRepository) SetCreateError(e error) { - repository.createErr = e + repository.createError = e } + func (repository *MockDripFileRepoRepository) AssertMarkHeaderCheckedCalledWith(i int64) { Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(i)) } + +func (repository *MockDripFileRepoRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/drip_file/vow/converter.go b/pkg/transformers/test_data/mocks/drip_file/vow/converter.go index 7d7adb29..4c9c0248 100644 --- a/pkg/transformers/test_data/mocks/drip_file/vow/converter.go +++ b/pkg/transformers/test_data/mocks/drip_file/vow/converter.go @@ -16,7 +16,6 @@ package vow import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) @@ -25,9 +24,9 @@ type MockDripFileVowConverter struct { PassedLogs []types.Log } -func (converter *MockDripFileVowConverter) ToModels(ethLogs []types.Log) ([]vow.DripFileVowModel, error) { +func (converter *MockDripFileVowConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []vow.DripFileVowModel{test_data.DripFileVowModel}, converter.converterErr + return []interface{}{test_data.DripFileVowModel}, converter.converterErr } func (converter *MockDripFileVowConverter) SetConverterError(e error) { diff --git a/pkg/transformers/test_data/mocks/drip_file/vow/repository.go b/pkg/transformers/test_data/mocks/drip_file/vow/repository.go index 54e36edd..2487ca42 100644 --- a/pkg/transformers/test_data/mocks/drip_file/vow/repository.go +++ b/pkg/transformers/test_data/mocks/drip_file/vow/repository.go @@ -16,46 +16,47 @@ package vow import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" ) type MockDripFileVowRepository struct { - createErr error - markHeaderCheckedErr error + createError error + markHeaderCheckedError error markHeaderCheckedPassedHeaderID int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error PassedStartingBlockNumber int64 PassedEndingBlockNumber int64 PassedHeaderID int64 - PassedModels []vow.DripFileVowModel + PassedModels []interface{} + SetDbCalled bool } -func (repository *MockDripFileVowRepository) Create(headerID int64, models []vow.DripFileVowModel) error { +func (repository *MockDripFileVowRepository) Create(headerID int64, models []interface{}) error { repository.PassedHeaderID = headerID repository.PassedModels = models - return repository.createErr + return repository.createError } func (repository *MockDripFileVowRepository) MarkHeaderChecked(headerID int64) error { repository.markHeaderCheckedPassedHeaderID = headerID - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } func (repository *MockDripFileVowRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } -func (repository *MockDripFileVowRepository) SetMarkHeaderCheckedErr(e error) { - repository.markHeaderCheckedErr = e +func (repository *MockDripFileVowRepository) SetMarkHeaderCheckedError(e error) { + repository.markHeaderCheckedError = e } -func (repository *MockDripFileVowRepository) SetMissingHeadersErr(e error) { - repository.missingHeadersErr = e +func (repository *MockDripFileVowRepository) SetMissingHeadersError(e error) { + repository.missingHeadersError = e } func (repository *MockDripFileVowRepository) SetMissingHeaders(headers []core.Header) { @@ -63,8 +64,12 @@ func (repository *MockDripFileVowRepository) SetMissingHeaders(headers []core.He } func (repository *MockDripFileVowRepository) SetCreateError(e error) { - repository.createErr = e + repository.createError = e } func (repository *MockDripFileVowRepository) AssertMarkHeaderCheckedCalledWith(i int64) { Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(i)) } + +func (repository *MockDripFileVowRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/log_fetcher.go b/pkg/transformers/test_data/mocks/log_fetcher.go index 463bf878..53172207 100644 --- a/pkg/transformers/test_data/mocks/log_fetcher.go +++ b/pkg/transformers/test_data/mocks/log_fetcher.go @@ -17,6 +17,7 @@ package mocks import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/vulcanize/vulcanizedb/pkg/core" ) type MockLogFetcher struct { @@ -25,6 +26,7 @@ type MockLogFetcher struct { FetchedBlocks []int64 fetcherError error FetchedLogs []types.Log + SetBcCalled bool } func (mlf *MockLogFetcher) FetchLogs(contractAddresses []string, topics [][]common.Hash, blockNumber int64) ([]types.Log, error) { @@ -35,6 +37,10 @@ func (mlf *MockLogFetcher) FetchLogs(contractAddresses []string, topics [][]comm return mlf.FetchedLogs, mlf.fetcherError } +func (mlf *MockLogFetcher) SetBC(bc core.BlockChain) { + mlf.SetBcCalled = true +} + func (mlf *MockLogFetcher) SetFetcherError(err error) { mlf.fetcherError = err } diff --git a/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/converter.go b/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/converter.go index f4ca9aa7..83d828b1 100644 --- a/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/converter.go +++ b/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/converter.go @@ -17,20 +17,19 @@ package debt_ceiling import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) type MockPitFileDebtCeilingConverter struct { - converterErr error - PassedLogs []types.Log + converterError error + PassedLogs []types.Log } -func (converter *MockPitFileDebtCeilingConverter) ToModels(ethLogs []types.Log) ([]debt_ceiling.PitFileDebtCeilingModel, error) { +func (converter *MockPitFileDebtCeilingConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []debt_ceiling.PitFileDebtCeilingModel{test_data.PitFileDebtCeilingModel}, converter.converterErr + return []interface{}{test_data.PitFileDebtCeilingModel}, converter.converterError } func (converter *MockPitFileDebtCeilingConverter) SetConverterError(e error) { - converter.converterErr = e + converter.converterError = e } diff --git a/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/repository.go b/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/repository.go index be06442e..7c9da60f 100644 --- a/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/repository.go +++ b/pkg/transformers/test_data/mocks/pit_file/debt_ceiling/repository.go @@ -16,46 +16,47 @@ package debt_ceiling import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" ) type MockPitFileDebtCeilingRepository struct { - createErr error - markHeaderCheckedErr error + createError error + markHeaderCheckedError error markHeaderCheckedPassedHeaderID int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error PassedStartingBlockNumber int64 PassedEndingBlockNumber int64 PassedHeaderID int64 - PassedModels []debt_ceiling.PitFileDebtCeilingModel + PassedModels []interface{} + SetDbCalled bool } func (repository *MockPitFileDebtCeilingRepository) MarkHeaderChecked(headerID int64) error { repository.markHeaderCheckedPassedHeaderID = headerID - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } -func (repository *MockPitFileDebtCeilingRepository) Create(headerID int64, models []debt_ceiling.PitFileDebtCeilingModel) error { +func (repository *MockPitFileDebtCeilingRepository) Create(headerID int64, models []interface{}) error { repository.PassedHeaderID = headerID repository.PassedModels = models - return repository.createErr + return repository.createError } func (repository *MockPitFileDebtCeilingRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } -func (repository *MockPitFileDebtCeilingRepository) SetMarkHeaderCheckedErr(e error) { - repository.markHeaderCheckedErr = e +func (repository *MockPitFileDebtCeilingRepository) SetMarkHeaderCheckedError(e error) { + repository.markHeaderCheckedError = e } -func (repository *MockPitFileDebtCeilingRepository) SetMissingHeadersErr(e error) { - repository.missingHeadersErr = e +func (repository *MockPitFileDebtCeilingRepository) SetMissingHeadersError(e error) { + repository.missingHeadersError = e } func (repository *MockPitFileDebtCeilingRepository) SetMissingHeaders(headers []core.Header) { @@ -63,9 +64,13 @@ func (repository *MockPitFileDebtCeilingRepository) SetMissingHeaders(headers [] } func (repository *MockPitFileDebtCeilingRepository) SetCreateError(e error) { - repository.createErr = e + repository.createError = e } func (repository *MockPitFileDebtCeilingRepository) AssertMarkHeaderCheckedCalledWith(i int64) { Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(i)) } + +func (repository *MockPitFileDebtCeilingRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/pit_file/ilk/converter.go b/pkg/transformers/test_data/mocks/pit_file/ilk/converter.go index d7052c42..0924b5e9 100644 --- a/pkg/transformers/test_data/mocks/pit_file/ilk/converter.go +++ b/pkg/transformers/test_data/mocks/pit_file/ilk/converter.go @@ -17,7 +17,6 @@ package ilk import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) @@ -30,7 +29,7 @@ func (converter *MockPitFileIlkConverter) SetConverterError(err error) { converter.converterError = err } -func (converter *MockPitFileIlkConverter) ToModels(ethLogs []types.Log) ([]ilk.PitFileIlkModel, error) { +func (converter *MockPitFileIlkConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []ilk.PitFileIlkModel{test_data.PitFileIlkModel}, converter.converterError + return []interface{}{test_data.PitFileIlkModel}, converter.converterError } diff --git a/pkg/transformers/test_data/mocks/pit_file/ilk/repository.go b/pkg/transformers/test_data/mocks/pit_file/ilk/repository.go index 4bb8db36..311b01a5 100644 --- a/pkg/transformers/test_data/mocks/pit_file/ilk/repository.go +++ b/pkg/transformers/test_data/mocks/pit_file/ilk/repository.go @@ -16,40 +16,41 @@ package ilk import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk" ) type MockPitFileIlkRepository struct { createError error PassedEndingBlockNumber int64 - PassedModels []ilk.PitFileIlkModel + PassedModels []interface{} PassedHeaderID int64 PassedStartingBlockNumber int64 - markHeaderCheckedErr error + markHeaderCheckedError error markHeaderCheckedPassedHeaderID int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error + SetDbCalled bool } func (repository *MockPitFileIlkRepository) SetCreateError(err error) { repository.createError = err } -func (repository *MockPitFileIlkRepository) SetMarkHeaderCheckedErr(e error) { - repository.markHeaderCheckedErr = e +func (repository *MockPitFileIlkRepository) SetMarkHeaderCheckedError(e error) { + repository.markHeaderCheckedError = e } -func (repository *MockPitFileIlkRepository) SetMissingHeadersErr(err error) { - repository.missingHeadersErr = err +func (repository *MockPitFileIlkRepository) SetMissingHeadersError(err error) { + repository.missingHeadersError = err } func (repository *MockPitFileIlkRepository) SetMissingHeaders(headers []core.Header) { repository.missingHeaders = headers } -func (repository *MockPitFileIlkRepository) Create(headerID int64, models []ilk.PitFileIlkModel) error { +func (repository *MockPitFileIlkRepository) Create(headerID int64, models []interface{}) error { repository.PassedHeaderID = headerID repository.PassedModels = models return repository.createError @@ -57,15 +58,19 @@ func (repository *MockPitFileIlkRepository) Create(headerID int64, models []ilk. func (repository *MockPitFileIlkRepository) MarkHeaderChecked(headerID int64) error { repository.markHeaderCheckedPassedHeaderID = headerID - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } func (repository *MockPitFileIlkRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } func (repository *MockPitFileIlkRepository) AssertMarkHeaderCheckedCalledWith(i int64) { Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(i)) } + +func (repository *MockPitFileIlkRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/pit_file/stability_fee/converter.go b/pkg/transformers/test_data/mocks/pit_file/stability_fee/converter.go index 8539d367..6e342cad 100644 --- a/pkg/transformers/test_data/mocks/pit_file/stability_fee/converter.go +++ b/pkg/transformers/test_data/mocks/pit_file/stability_fee/converter.go @@ -17,20 +17,19 @@ package stability_fee import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) type MockPitFileStabilityFeeConverter struct { - converterErr error - PassedLogs []types.Log + converterError error + PassedLogs []types.Log } -func (converter *MockPitFileStabilityFeeConverter) ToModels(ethLogs []types.Log) ([]stability_fee.PitFileStabilityFeeModel, error) { +func (converter *MockPitFileStabilityFeeConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []stability_fee.PitFileStabilityFeeModel{test_data.PitFileStabilityFeeModel}, converter.converterErr + return []interface{}{test_data.PitFileStabilityFeeModel}, converter.converterError } func (converter *MockPitFileStabilityFeeConverter) SetConverterError(e error) { - converter.converterErr = e + converter.converterError = e } diff --git a/pkg/transformers/test_data/mocks/pit_file/stability_fee/repository.go b/pkg/transformers/test_data/mocks/pit_file/stability_fee/repository.go index 907538a8..e20678e1 100644 --- a/pkg/transformers/test_data/mocks/pit_file/stability_fee/repository.go +++ b/pkg/transformers/test_data/mocks/pit_file/stability_fee/repository.go @@ -16,46 +16,47 @@ package stability_fee import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee" ) type MockPitFileStabilityFeeRepository struct { - createErr error - markHeaderCheckedErr error + createError error + markHeaderCheckedError error markHeaderCheckedPassedHeaderID int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error PassedStartingBlockNumber int64 PassedEndingBlockNumber int64 PassedHeaderID int64 - PassedModels []stability_fee.PitFileStabilityFeeModel + PassedModels []interface{} + SetDbCalled bool } -func (repository *MockPitFileStabilityFeeRepository) Create(headerID int64, models []stability_fee.PitFileStabilityFeeModel) error { +func (repository *MockPitFileStabilityFeeRepository) Create(headerID int64, models []interface{}) error { repository.PassedModels = models repository.PassedHeaderID = headerID - return repository.createErr + return repository.createError } func (repository *MockPitFileStabilityFeeRepository) MarkHeaderChecked(headerID int64) error { repository.markHeaderCheckedPassedHeaderID = headerID - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } func (repository *MockPitFileStabilityFeeRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } func (repository *MockPitFileStabilityFeeRepository) SetMarkHeaderCheckedErr(e error) { - repository.markHeaderCheckedErr = e + repository.markHeaderCheckedError = e } func (repository *MockPitFileStabilityFeeRepository) SetMissingHeadersErr(e error) { - repository.missingHeadersErr = e + repository.missingHeadersError = e } func (repository *MockPitFileStabilityFeeRepository) SetMissingHeaders(headers []core.Header) { @@ -63,9 +64,13 @@ func (repository *MockPitFileStabilityFeeRepository) SetMissingHeaders(headers [ } func (repository *MockPitFileStabilityFeeRepository) SetCreateError(e error) { - repository.createErr = e + repository.createError = e } func (repository *MockPitFileStabilityFeeRepository) AssertMarkHeaderCheckedCalledWith(i int64) { Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(i)) } + +func (repository *MockPitFileStabilityFeeRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/tend/converter.go b/pkg/transformers/test_data/mocks/tend/converter.go index 77ec60c9..2669e965 100644 --- a/pkg/transformers/test_data/mocks/tend/converter.go +++ b/pkg/transformers/test_data/mocks/tend/converter.go @@ -17,20 +17,19 @@ package tend import ( "github.com/ethereum/go-ethereum/core/types" - "github.com/vulcanize/vulcanizedb/pkg/transformers/tend" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" ) type MockTendConverter struct { - LogsToConvert []types.Log + PassedLogs []types.Log ConverterError error } -func (c *MockTendConverter) ToModels(ethLogs []types.Log) ([]tend.TendModel, error) { - c.LogsToConvert = append(c.LogsToConvert, ethLogs...) - return []tend.TendModel{test_data.TendModel}, c.ConverterError +func (converter *MockTendConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + converter.PassedLogs = ethLogs + return []interface{}{test_data.TendModel}, converter.ConverterError } -func (c *MockTendConverter) SetConverterError(err error) { - c.ConverterError = err +func (converter *MockTendConverter) SetConverterError(err error) { + converter.ConverterError = err } diff --git a/pkg/transformers/test_data/mocks/tend/repository.go b/pkg/transformers/test_data/mocks/tend/repository.go index 6bb7da13..b013b9ab 100644 --- a/pkg/transformers/test_data/mocks/tend/repository.go +++ b/pkg/transformers/test_data/mocks/tend/repository.go @@ -16,9 +16,9 @@ package tend import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/tend" ) type MockTendRepository struct { @@ -26,14 +26,15 @@ type MockTendRepository struct { PassedEndingBlockNumber int64 PassedHeaderID int64 PassedStartingBlockNumber int64 - PassedTendModel tend.TendModel - markHeaderCheckedErr error + PassedTendModel interface{} + markHeaderCheckedError error markHeaderCheckedPassedHeaderId int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error + SetDbCalled bool } -func (repository *MockTendRepository) Create(headerId int64, tend []tend.TendModel) error { +func (repository *MockTendRepository) Create(headerId int64, tend []interface{}) error { repository.PassedHeaderID = headerId repository.PassedTendModel = tend[0] return repository.createError @@ -44,11 +45,11 @@ func (repository *MockTendRepository) SetCreateError(err error) { } func (repository *MockTendRepository) SetMarkHeaderCheckedErr(err error) { - repository.markHeaderCheckedErr = err + repository.markHeaderCheckedError = err } func (repository *MockTendRepository) SetMissingHeadersErr(err error) { - repository.missingHeadersErr = err + repository.missingHeadersError = err } func (repository *MockTendRepository) SetMissingHeaders(headers []core.Header) { @@ -57,15 +58,19 @@ func (repository *MockTendRepository) SetMissingHeaders(headers []core.Header) { func (repository *MockTendRepository) MarkHeaderChecked(headerId int64) error { repository.markHeaderCheckedPassedHeaderId = headerId - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } func (repository *MockTendRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } func (repository *MockTendRepository) AssertMarkHeaderCheckedCalledWith(headerId int64) { Expect(repository.markHeaderCheckedPassedHeaderId).To(Equal(headerId)) } + +func (repository *MockTendRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/vat_init/converter.go b/pkg/transformers/test_data/mocks/vat_init/converter.go index 3b8b9ccd..dcc0b3a1 100644 --- a/pkg/transformers/test_data/mocks/vat_init/converter.go +++ b/pkg/transformers/test_data/mocks/vat_init/converter.go @@ -18,19 +18,18 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" - "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_init" ) type MockVatInitConverter struct { - converterErr error - PassedLogs []types.Log + converterError error + PassedLogs []types.Log } -func (converter *MockVatInitConverter) ToModels(ethLogs []types.Log) ([]vat_init.VatInitModel, error) { +func (converter *MockVatInitConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []vat_init.VatInitModel{test_data.VatInitModel}, converter.converterErr + return []interface{}{test_data.VatInitModel}, converter.converterError } func (converter *MockVatInitConverter) SetConverterError(e error) { - converter.converterErr = e + converter.converterError = e } diff --git a/pkg/transformers/test_data/mocks/vat_init/repository.go b/pkg/transformers/test_data/mocks/vat_init/repository.go index 7a9978b6..fccbdc0c 100644 --- a/pkg/transformers/test_data/mocks/vat_init/repository.go +++ b/pkg/transformers/test_data/mocks/vat_init/repository.go @@ -16,46 +16,47 @@ package vat_init import ( . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_init" ) type MockVatInitRepository struct { - createErr error - markHeaderCheckedErr error + createError error + markHeaderCheckedError error markHeaderCheckedPassedHeaderID int64 missingHeaders []core.Header - missingHeadersErr error + missingHeadersError error PassedStartingBlockNumber int64 PassedEndingBlockNumber int64 PassedHeaderID int64 - PassedModels []vat_init.VatInitModel + PassedModels []interface{} + SetDbCalled bool } -func (repository *MockVatInitRepository) Create(headerID int64, models []vat_init.VatInitModel) error { +func (repository *MockVatInitRepository) Create(headerID int64, models []interface{}) error { repository.PassedHeaderID = headerID repository.PassedModels = models - return repository.createErr + return repository.createError } func (repository *MockVatInitRepository) MarkHeaderChecked(headerID int64) error { repository.markHeaderCheckedPassedHeaderID = headerID - return repository.markHeaderCheckedErr + return repository.markHeaderCheckedError } func (repository *MockVatInitRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) { repository.PassedStartingBlockNumber = startingBlockNumber repository.PassedEndingBlockNumber = endingBlockNumber - return repository.missingHeaders, repository.missingHeadersErr + return repository.missingHeaders, repository.missingHeadersError } -func (repository *MockVatInitRepository) SetMarkHeaderCheckedErr(e error) { - repository.markHeaderCheckedErr = e +func (repository *MockVatInitRepository) SetMarkHeaderCheckedError(e error) { + repository.markHeaderCheckedError = e } -func (repository *MockVatInitRepository) SetMissingHeadersErr(e error) { - repository.missingHeadersErr = e +func (repository *MockVatInitRepository) SetMissingHeadersError(e error) { + repository.missingHeadersError = e } func (repository *MockVatInitRepository) SetMissingHeaders(headers []core.Header) { @@ -63,9 +64,13 @@ func (repository *MockVatInitRepository) SetMissingHeaders(headers []core.Header } func (repository *MockVatInitRepository) SetCreateError(e error) { - repository.createErr = e + repository.createError = e } func (repository *MockVatInitRepository) AssertMarkHeaderCheckedCalledWith(i int64) { Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(i)) } + +func (repository *MockVatInitRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/mocks/vat_move/converter.go b/pkg/transformers/test_data/mocks/vat_move/converter.go index b11d1830..6650e9ed 100644 --- a/pkg/transformers/test_data/mocks/vat_move/converter.go +++ b/pkg/transformers/test_data/mocks/vat_move/converter.go @@ -17,7 +17,6 @@ package vat_move import ( "github.com/ethereum/go-ethereum/core/types" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" - "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move" ) type MockVatMoveConverter struct { @@ -25,9 +24,9 @@ type MockVatMoveConverter struct { PassedLogs []types.Log } -func (converter *MockVatMoveConverter) ToModels(ethLogs []types.Log) ([]vat_move.VatMoveModel, error) { +func (converter *MockVatMoveConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { converter.PassedLogs = ethLogs - return []vat_move.VatMoveModel{test_data.VatMoveModel}, converter.converterError + return []interface{}{test_data.VatMoveModel}, converter.converterError } func (converter *MockVatMoveConverter) SetConverterError(e error) { diff --git a/pkg/transformers/test_data/mocks/vat_move/repository.go b/pkg/transformers/test_data/mocks/vat_move/repository.go index 20d578e7..d1ce0859 100644 --- a/pkg/transformers/test_data/mocks/vat_move/repository.go +++ b/pkg/transformers/test_data/mocks/vat_move/repository.go @@ -16,7 +16,7 @@ package vat_move import ( "github.com/vulcanize/vulcanizedb/pkg/core" - "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) type MockVatMoveRepository struct { @@ -26,12 +26,13 @@ type MockVatMoveRepository struct { PassedStartingBlockNumber int64 PassedEndingBlockNumber int64 PassedHeaderID int64 - PassedModels []vat_move.VatMoveModel + PassedModels []interface{} CheckedHeaderIDs []int64 CheckedHeaderError error + SetDbCalled bool } -func (repository *MockVatMoveRepository) Create(headerID int64, models []vat_move.VatMoveModel) error { +func (repository *MockVatMoveRepository) Create(headerID int64, models []interface{}) error { repository.PassedHeaderID = headerID repository.PassedModels = models return repository.createError @@ -63,3 +64,7 @@ func (repository *MockVatMoveRepository) MarkHeaderChecked(headerId int64) error func (repository *MockVatMoveRepository) SetCheckedHeaderError(e error) { repository.CheckedHeaderError = e } + +func (repository *MockVatMoveRepository) SetDB(db *postgres.DB) { + repository.SetDbCalled = true +} diff --git a/pkg/transformers/test_data/wrong_model.go b/pkg/transformers/test_data/wrong_model.go new file mode 100644 index 00000000..607cad52 --- /dev/null +++ b/pkg/transformers/test_data/wrong_model.go @@ -0,0 +1,17 @@ +// 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 test_data + +type WrongModel struct{} diff --git a/pkg/transformers/transformers.go b/pkg/transformers/transformers.go index 3e404697..2cf296ff 100644 --- a/pkg/transformers/transformers.go +++ b/pkg/transformers/transformers.go @@ -23,14 +23,13 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/deal" "github.com/vulcanize/vulcanizedb/pkg/transformers/dent" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_drip" - "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file" ilk2 "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/repo" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/flop_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/frob" - "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk" "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee" @@ -49,36 +48,86 @@ import ( ) var ( - BiteTransformerInitializer = bite.BiteTransformerInitializer{Config: bite.BiteConfig}.NewBiteTransformer - catFileConfig = cat_file.CatFileConfig - CatFileChopLumpTransformerInitializer = chop_lump.CatFileChopLumpTransformerInitializer{Config: catFileConfig}.NewCatFileChopLumpTransformer - CatFileFlipTransformerInitializer = flip.CatFileFlipTransformerInitializer{Config: catFileConfig}.NewCatFileFlipTransformer - CatFilePitVowTransformerInitializer = pit_vow.CatFilePitVowTransformerInitializer{Config: catFileConfig}.NewCatFilePitVowTransformer - DealTransformerInitializer = deal.DealTransformerInitializer{Config: deal.Config}.NewDealTransformer - DentTransformerInitializer = dent.DentTransformerInitializer{Config: dent.DentConfig}.NewDentTransformer - DripDripTransformerInitializer = drip_drip.DripDripTransformerInitializer{Config: drip_drip.DripDripConfig}.NewDripDripTransformer - dripFileConfig = drip_file.DripFileConfig - DripFileIlkTransformerInitializer = ilk2.DripFileIlkTransformerInitializer{Config: dripFileConfig}.NewDripFileIlkTransformer - DripFileRepoTransformerInitializer = repo.DripFileRepoTransformerInitializer{Config: dripFileConfig}.NewDripFileRepoTransformer - DripFileVowTransfromerInitializer = vow.DripFileVowTransformerInitializer{Config: dripFileConfig}.NewDripFileVowTransformer - FlipKickTransformerInitializer = flip_kick.FlipKickTransformerInitializer{Config: flip_kick.FlipKickConfig}.NewFlipKickTransformer - FlopKickTransformerInitializer = flop_kick.FlopKickTransformerInitializer{Config: flop_kick.Config}.NewFlopKickTransformer - FrobTransformerInitializer = frob.FrobTransformerInitializer{Config: frob.FrobConfig}.NewFrobTransformer - pitFileConfig = pit_file.PitFileConfig - PitFileDebtCeilingTransformerInitializer = debt_ceiling.PitFileDebtCeilingTransformerInitializer{Config: pitFileConfig}.NewPitFileDebtCeilingTransformer - PitFileIlkTransformerInitializer = ilk.PitFileIlkTransformerInitializer{Config: pitFileConfig}.NewPitFileIlkTransformer - PitFileStabilityFeeTransformerInitializer = stability_fee.PitFileStabilityFeeTransformerInitializer{Config: pitFileConfig}.NewPitFileStabilityFeeTransformer - PriceFeedTransformerInitializer = price_feeds.PriceFeedTransformerInitializer{Config: price_feeds.PriceFeedConfig}.NewPriceFeedTransformer - TendTransformerInitializer = tend.TendTransformerInitializer{Config: tend.TendConfig}.NewTendTransformer - VatGrabTransformerInitializer = vat_grab.VatGrabTransformerInitializer{Config: vat_grab.VatGrabConfig}.NewVatGrabTransformer - VatInitTransformerInitializer = vat_init.VatInitTransformerInitializer{Config: vat_init.VatInitConfig}.NewVatInitTransformer - VatMoveTransformerInitializer = vat_move.VatMoveTransformerInitializer{Config: vat_move.VatMoveConfig}.NewVatMoveTransformer - VatHealTransformerInitializer = vat_heal.VatHealTransformerInitializer{Config: vat_heal.VatHealConfig}.NewVatHealTransformer - VatFoldTransformerInitializer = vat_fold.VatFoldTransformerInitializer{Config: vat_fold.VatFoldConfig}.NewVatFoldTransformer - VatSlipTransformerInitializer = vat_slip.VatSlipTransformerInitializer{Config: vat_slip.VatSlipConfig}.NewVatSlipTransformer - VatTollTransformerInitializer = vat_toll.VatTollTransformerInitializer{Config: vat_toll.VatTollConfig}.NewVatTollTransformer - VatTuneTransformerInitializer = vat_tune.VatTuneTransformerInitializer{Config: vat_tune.VatTuneConfig}.NewVatTuneTransformer - VatFluxTransformerInitializer = vat_flux.VatFluxTransformerInitializer{Config: vat_flux.VatFluxConfig}.NewVatFluxTransformer + BiteTransformerInitializer = bite.BiteTransformerInitializer{Config: bite.BiteConfig}.NewBiteTransformer + catFileConfig = cat_file.CatFileConfig + CatFileChopLumpTransformerInitializer = chop_lump.CatFileChopLumpTransformerInitializer{Config: catFileConfig}.NewCatFileChopLumpTransformer + CatFileFlipTransformerInitializer = flip.CatFileFlipTransformerInitializer{Config: catFileConfig}.NewCatFileFlipTransformer + CatFilePitVowTransformerInitializer = pit_vow.CatFilePitVowTransformerInitializer{Config: catFileConfig}.NewCatFilePitVowTransformer + DealTransformerInitializer = deal.DealTransformerInitializer{Config: deal.Config}.NewDealTransformer + DentTransformerInitializer = dent.DentTransformerInitializer{Config: dent.DentConfig}.NewDentTransformer + DripDripTransformerInitializer = drip_drip.DripDripTransformerInitializer{Config: drip_drip.DripDripConfig}.NewDripDripTransformer + DripFileIlkTransformerInitializer = factories.Transformer{ + Config: ilk2.DripFileIlkConfig, + Converter: &ilk2.DripFileIlkConverter{}, + Repository: &ilk2.DripFileIlkRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + DripFileRepoTransformerInitializer = factories.Transformer{ + Config: repo.DripFileRepoConfig, + Converter: &repo.DripFileRepoConverter{}, + Repository: &repo.DripFileRepoRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + DripFileVowTransfromerInitializer = factories.Transformer{ + Config: vow.DripFileVowConfig, + Converter: &vow.DripFileVowConverter{}, + Repository: &vow.DripFileVowRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + FlipKickTransformerInitializer = flip_kick.FlipKickTransformerInitializer{Config: flip_kick.FlipKickConfig}.NewFlipKickTransformer + FlopKickTransformerInitializer = flop_kick.FlopKickTransformerInitializer{Config: flop_kick.Config}.NewFlopKickTransformer + FrobTransformerInitializer = frob.FrobTransformerInitializer{Config: frob.FrobConfig}.NewFrobTransformer + PitFileDebtCeilingTransformerInitializer = factories.Transformer{ + Config: debt_ceiling.DebtCeilingFileConfig, + Converter: &debt_ceiling.PitFileDebtCeilingConverter{}, + Repository: &debt_ceiling.PitFileDebtCeilingRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + PitFileIlkTransformerInitializer = factories.Transformer{ + Config: ilk.IlkFileConfig, + Converter: &ilk.PitFileIlkConverter{}, + Repository: &ilk.PitFileIlkRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + PitFileStabilityFeeTransformerInitializer = factories.Transformer{ + Config: stability_fee.StabilityFeeFileConfig, + Converter: &stability_fee.PitFileStabilityFeeConverter{}, + Repository: &stability_fee.PitFileStabilityFeeRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + PriceFeedTransformerInitializer = price_feeds.PriceFeedTransformerInitializer{Config: price_feeds.PriceFeedConfig}.NewPriceFeedTransformer + TendTransformerInitializer = factories.Transformer{ + Config: tend.TendConfig, + Converter: &tend.TendConverter{}, + Repository: &tend.TendRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + + VatInitTransformerInitializer = factories.Transformer{ + Config: vat_init.VatInitConfig, + Converter: &vat_init.VatInitConverter{}, + Repository: &vat_init.VatInitRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + VatGrabTransformerInitializer = vat_grab.VatGrabTransformerInitializer{Config: vat_grab.VatGrabConfig}.NewVatGrabTransformer + VatHealTransformerInitializer = vat_heal.VatHealTransformerInitializer{Config: vat_heal.VatHealConfig}.NewVatHealTransformer + VatFoldTransformerInitializer = vat_fold.VatFoldTransformerInitializer{Config: vat_fold.VatFoldConfig}.NewVatFoldTransformer + VatMoveTransformerInitializer = factories.Transformer{ + Config: vat_move.VatMoveConfig, + Converter: &vat_move.VatMoveConverter{}, + Repository: &vat_move.VatMoveRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + VatSlipTransformerInitializer = vat_slip.VatSlipTransformerInitializer{Config: vat_slip.VatSlipConfig}.NewVatSlipTransformer + VatTollTransformerInitializer = vat_toll.VatTollTransformerInitializer{Config: vat_toll.VatTollConfig}.NewVatTollTransformer + VatTuneTransformerInitializer = vat_tune.VatTuneTransformerInitializer{Config: vat_tune.VatTuneConfig}.NewVatTuneTransformer + VatFluxTransformerInitializer = vat_flux.VatFluxTransformerInitializer{Config: vat_flux.VatFluxConfig}.NewVatFluxTransformer ) func TransformerInitializers() []shared.TransformerInitializer { diff --git a/pkg/transformers/vat_init/config.go b/pkg/transformers/vat_init/config.go index dcc9a03e..d54abb56 100644 --- a/pkg/transformers/vat_init/config.go +++ b/pkg/transformers/vat_init/config.go @@ -18,10 +18,11 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) -var VatInitConfig = shared.TransformerConfig{ +var VatInitConfig = shared.SingleTransformerConfig{ + TransformerName: shared.VatInitLabel, ContractAddresses: []string{shared.VatContractAddress}, ContractAbi: shared.VatABI, - Topics: []string{shared.VatInitSignature}, + Topic: shared.VatInitSignature, StartingBlockNumber: 0, EndingBlockNumber: 10000000, } diff --git a/pkg/transformers/vat_init/converter.go b/pkg/transformers/vat_init/converter.go index 7fc510b5..88f40fdf 100644 --- a/pkg/transformers/vat_init/converter.go +++ b/pkg/transformers/vat_init/converter.go @@ -18,18 +18,13 @@ import ( "bytes" "encoding/json" "errors" - "github.com/ethereum/go-ethereum/core/types" ) -type Converter interface { - ToModels(ethLogs []types.Log) ([]VatInitModel, error) -} - type VatInitConverter struct{} -func (VatInitConverter) ToModels(ethLogs []types.Log) ([]VatInitModel, error) { - var models []VatInitModel +func (VatInitConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { diff --git a/pkg/transformers/vat_init/converter_test.go b/pkg/transformers/vat_init/converter_test.go index f07625ba..f7e158bc 100644 --- a/pkg/transformers/vat_init/converter_test.go +++ b/pkg/transformers/vat_init/converter_test.go @@ -24,18 +24,20 @@ import ( ) var _ = Describe("Vat init converter", func() { - It("returns err if log missing topics", func() { - converter := vat_init.VatInitConverter{} - badLog := types.Log{} + var converter vat_init.VatInitConverter + BeforeEach(func() { + converter = vat_init.VatInitConverter{} + }) + + It("returns err if log missing topics", func() { + badLog := types.Log{} _, err := converter.ToModels([]types.Log{badLog}) Expect(err).To(HaveOccurred()) }) It("converts a log to an model", func() { - converter := vat_init.VatInitConverter{} - models, err := converter.ToModels([]types.Log{test_data.EthVatInitLog}) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/vat_init/repository.go b/pkg/transformers/vat_init/repository.go index f17d91c5..b581b8b1 100644 --- a/pkg/transformers/vat_init/repository.go +++ b/pkg/transformers/vat_init/repository.go @@ -15,42 +15,42 @@ package vat_init import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "log" ) -type Repository interface { - Create(headerID int64, models []VatInitModel) error - MarkHeaderChecked(headerID int64) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) -} - type VatInitRepository struct { db *postgres.DB } -func NewVatInitRepository(db *postgres.DB) VatInitRepository { - return VatInitRepository{ - db: db, - } -} - -func (repository VatInitRepository) Create(headerID int64, models []VatInitModel) error { +func (repository VatInitRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } + for _, model := range models { + vatInit, ok := model.(VatInitModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, VatInitModel{}) + } + + log.Printf("VatInit model: %v", vatInit) _, err = tx.Exec( - `INSERT into maker.vat_init (header_id, ilk, tx_idx, raw_log) - VALUES($1, $2, $3, $4)`, - headerID, model.Ilk, model.TransactionIndex, model.Raw, + `INSERT INTO maker.vat_init (header_id, ilk, tx_idx, raw_log) + VALUES($1, $2, $3, $4)`, + headerID, vatInit.Ilk, vatInit.TransactionIndex, vatInit.Raw, ) if err != nil { tx.Rollback() + log.Printf("Error: %v \n", err) return err } } + _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, vat_init_checked) VALUES($1, $2) ON CONFLICT (header_id) DO @@ -87,3 +87,7 @@ func (repository VatInitRepository) MissingHeaders(startingBlockNumber, endingBl ) return result, err } + +func (repository *VatInitRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/vat_init/repository_test.go b/pkg/transformers/vat_init/repository_test.go index ec84008d..28d1f29d 100644 --- a/pkg/transformers/vat_init/repository_test.go +++ b/pkg/transformers/vat_init/repository_test.go @@ -16,6 +16,7 @@ package vat_init_test import ( "database/sql" + "math/rand" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -32,7 +33,7 @@ import ( var _ = Describe("Vat init repository", func() { var ( db *postgres.DB - vatInitRepository vat_init.Repository + vatInitRepository vat_init.VatInitRepository headerRepository repositories.HeaderRepository err error ) @@ -40,7 +41,8 @@ var _ = Describe("Vat init repository", func() { BeforeEach(func() { db = test_config.NewTestDB(core.Node{}) test_config.CleanTestDB(db) - vatInitRepository = vat_init.NewVatInitRepository(db) + vatInitRepository = vat_init.VatInitRepository{} + vatInitRepository.SetDB(db) headerRepository = repositories.NewHeaderRepository(db) }) @@ -51,13 +53,13 @@ var _ = Describe("Vat init repository", func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = vatInitRepository.Create(headerID, []vat_init.VatInitModel{test_data.VatInitModel}) + err = vatInitRepository.Create(headerID, []interface{}{test_data.VatInitModel}) Expect(err).NotTo(HaveOccurred()) }) It("adds a vat event", func() { var dbVatInit vat_init.VatInitModel - err = db.Get(&dbVatInit, `SELECT ilk,tx_idx, raw_log FROM maker.vat_init WHERE header_id = $1`, headerID) + err = db.Get(&dbVatInit, `SELECT ilk, tx_idx, raw_log FROM maker.vat_init WHERE header_id = $1`, headerID) Expect(err).NotTo(HaveOccurred()) Expect(dbVatInit.Ilk).To(Equal(test_data.VatInitModel.Ilk)) Expect(dbVatInit.TransactionIndex).To(Equal(test_data.VatInitModel.TransactionIndex)) @@ -65,7 +67,7 @@ var _ = Describe("Vat init repository", func() { }) It("does not duplicate vat events", func() { - err = vatInitRepository.Create(headerID, []vat_init.VatInitModel{test_data.VatInitModel}) + err = vatInitRepository.Create(headerID, []interface{}{test_data.VatInitModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) @@ -87,6 +89,12 @@ var _ = Describe("Vat init repository", func() { Expect(err).NotTo(HaveOccurred()) Expect(headerChecked).To(BeTrue()) }) + + It("Returns an error if model is of wrong type", func() { + err = vatInitRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MarkHeaderChecked", func() { @@ -95,7 +103,6 @@ var _ = Describe("Vat init repository", func() { BeforeEach(func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - }) It("creates a row for a new headerID", func() { @@ -128,7 +135,7 @@ var _ = Describe("Vat init repository", func() { ) BeforeEach(func() { - startingBlock = GinkgoRandomSeed() + startingBlock = rand.Int63() vatInitBlock = startingBlock + 1 endingBlock = startingBlock + 2 @@ -174,8 +181,10 @@ var _ = Describe("Vat init repository", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - vatInitRepositoryTwo := vat_init.NewVatInitRepository(dbTwo) - err := vatInitRepository.MarkHeaderChecked(headerIDs[0]) + + vatInitRepositoryTwo := vat_init.VatInitRepository{} + vatInitRepositoryTwo.SetDB(dbTwo) + err = vatInitRepository.MarkHeaderChecked(headerIDs[0]) Expect(err).NotTo(HaveOccurred()) nodeOneMissingHeaders, err := vatInitRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) diff --git a/pkg/transformers/vat_init/transformer.go b/pkg/transformers/vat_init/transformer.go deleted file mode 100644 index 2404f67b..00000000 --- a/pkg/transformers/vat_init/transformer.go +++ /dev/null @@ -1,78 +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 vat_init - -import ( - "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 VatInitTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer VatInitTransformerInitializer) NewVatInitTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := VatInitConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewVatInitRepository(db) - return VatInitTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -type VatInitTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -func (transformer VatInitTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - log.Printf("Fetching vat init event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.VatInitSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(VatInitConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - if len(matchingLogs) < 1 { - err = transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - } - models, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - err = transformer.Repository.Create(header.Id, models) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/vat_init/transformer_test.go b/pkg/transformers/vat_init/transformer_test.go index 95d2acab..9df2e1da 100644 --- a/pkg/transformers/vat_init/transformer_test.go +++ b/pkg/transformers/vat_init/transformer_test.go @@ -19,6 +19,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/fakes" @@ -30,15 +32,36 @@ import ( ) var _ = Describe("Vat init transformer", func() { - It("gets missing headers for block numbers specified in config", func() { - repository := &vat_init_mocks.MockVatInitRepository{} - transformer := vat_init.VatInitTransformer{ - Config: vat_init.VatInitConfig, - Fetcher: &mocks.MockLogFetcher{}, - Converter: &vat_init_mocks.MockVatInitConverter{}, - Repository: repository, - } + var ( + config = vat_init.VatInitConfig + converter vat_init_mocks.MockVatInitConverter + repository vat_init_mocks.MockVatInitRepository + fetcher mocks.MockLogFetcher + transformer shared.Transformer + headerOne core.Header + headerTwo core.Header + ) + BeforeEach(func() { + converter = vat_init_mocks.MockVatInitConverter{} + repository = vat_init_mocks.MockVatInitRepository{} + fetcher = mocks.MockLogFetcher{} + headerOne = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + headerTwo = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + transformer = factories.Transformer{ + Config: config, + Fetcher: &fetcher, + Converter: &converter, + Repository: &repository, + }.NewTransformer(nil, nil) + }) + + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) @@ -47,13 +70,7 @@ var _ = Describe("Vat init transformer", func() { }) It("returns error if repository returns error for missing headers", func() { - repository := &vat_init_mocks.MockVatInitRepository{} - repository.SetMissingHeadersErr(fakes.FakeError) - transformer := vat_init.VatInitTransformer{ - Fetcher: &mocks.MockLogFetcher{}, - Converter: &vat_init_mocks.MockVatInitConverter{}, - Repository: repository, - } + repository.SetMissingHeadersError(fakes.FakeError) err := transformer.Execute() @@ -62,33 +79,20 @@ var _ = Describe("Vat init transformer", func() { }) It("fetches logs for missing headers", func() { - fetcher := &mocks.MockLogFetcher{} - repository := &vat_init_mocks.MockVatInitRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}, {BlockNumber: 2}}) - transformer := vat_init.VatInitTransformer{ - Fetcher: fetcher, - Converter: &vat_init_mocks.MockVatInitConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) - Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{vat_init.VatInitConfig.ContractAddresses, vat_init.VatInitConfig.ContractAddresses})) + Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber})) + Expect(fetcher.FetchedContractAddresses).To(Equal( + [][]string{config.ContractAddresses, config.ContractAddresses})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.VatInitSignature)}})) }) It("returns error if fetcher returns error", func() { - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetcherError(fakes.FakeError) - repository := &vat_init_mocks.MockVatInitRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := vat_init.VatInitTransformer{ - Fetcher: fetcher, - Converter: &vat_init_mocks.MockVatInitConverter{}, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -97,34 +101,17 @@ var _ = Describe("Vat init transformer", func() { }) It("marks header checked if no logs returned", func() { - mockConverter := &vat_init_mocks.MockVatInitConverter{} - mockRepository := &vat_init_mocks.MockVatInitRepository{} - headerID := int64(123) - mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}}) - mockFetcher := &mocks.MockLogFetcher{} - transformer := vat_init.VatInitTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - mockRepository.AssertMarkHeaderCheckedCalledWith(headerID) + repository.AssertMarkHeaderCheckedCalledWith(headerOne.Id) }) It("returns error if marking header checked returns err", func() { - mockConverter := &vat_init_mocks.MockVatInitConverter{} - mockRepository := &vat_init_mocks.MockVatInitRepository{} - mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}}) - mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError) - mockFetcher := &mocks.MockLogFetcher{} - transformer := vat_init.VatInitTransformer{ - Converter: mockConverter, - Fetcher: mockFetcher, - Repository: mockRepository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) + repository.SetMarkHeaderCheckedError(fakes.FakeError) err := transformer.Execute() @@ -133,16 +120,8 @@ var _ = Describe("Vat init transformer", func() { }) It("converts matching logs", func() { - converter := &vat_init_mocks.MockVatInitConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthVatInitLog}) - repository := &vat_init_mocks.MockVatInitRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := vat_init.VatInitTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -151,17 +130,9 @@ var _ = Describe("Vat init transformer", func() { }) It("returns error if converter returns error", func() { - converter := &vat_init_mocks.MockVatInitConverter{} converter.SetConverterError(fakes.FakeError) - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthVatInitLog}) - repository := &vat_init_mocks.MockVatInitRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}}) - transformer := vat_init.VatInitTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() @@ -170,37 +141,20 @@ var _ = Describe("Vat init transformer", func() { }) It("persists vat init model", func() { - converter := &vat_init_mocks.MockVatInitConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthVatInitLog}) - repository := &vat_init_mocks.MockVatInitRepository{} - fakeHeader := core.Header{BlockNumber: 1, Id: 2} - repository.SetMissingHeaders([]core.Header{fakeHeader}) - transformer := vat_init.VatInitTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } + repository.SetMissingHeaders([]core.Header{headerOne}) err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) - Expect(repository.PassedModels).To(Equal([]vat_init.VatInitModel{test_data.VatInitModel})) + Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.VatInitModel})) }) It("returns error if repository returns error for create", func() { - converter := &vat_init_mocks.MockVatInitConverter{} - fetcher := &mocks.MockLogFetcher{} fetcher.SetFetchedLogs([]types.Log{test_data.EthVatInitLog}) - repository := &vat_init_mocks.MockVatInitRepository{} - repository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}}) + repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := vat_init.VatInitTransformer{ - Fetcher: fetcher, - Converter: converter, - Repository: repository, - } err := transformer.Execute() diff --git a/pkg/transformers/vat_move/config.go b/pkg/transformers/vat_move/config.go index 32077783..93f25e55 100644 --- a/pkg/transformers/vat_move/config.go +++ b/pkg/transformers/vat_move/config.go @@ -18,10 +18,11 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" ) -var VatMoveConfig = shared.TransformerConfig{ +var VatMoveConfig = shared.SingleTransformerConfig{ + TransformerName: shared.VatMoveLabel, ContractAddresses: []string{shared.VatContractAddress}, ContractAbi: shared.VatABI, - Topics: []string{shared.VatMoveSignature}, + Topic: shared.VatMoveSignature, StartingBlockNumber: 0, EndingBlockNumber: 10000000, } diff --git a/pkg/transformers/vat_move/converter.go b/pkg/transformers/vat_move/converter.go index c28aa71a..4896a786 100644 --- a/pkg/transformers/vat_move/converter.go +++ b/pkg/transformers/vat_move/converter.go @@ -21,18 +21,14 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -type Converter interface { - ToModels(ethLog []types.Log) ([]VatMoveModel, error) -} - type VatMoveConverter struct{} -func (VatMoveConverter) ToModels(ethLogs []types.Log) ([]VatMoveModel, error) { - var models []VatMoveModel +func (VatMoveConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) { + var models []interface{} for _, ethLog := range ethLogs { err := verifyLog(ethLog) if err != nil { - return []VatMoveModel{}, err + return []interface{}{}, err } src := common.BytesToAddress(ethLog.Topics[1].Bytes()) @@ -40,7 +36,7 @@ func (VatMoveConverter) ToModels(ethLogs []types.Log) ([]VatMoveModel, error) { rad := ethLog.Topics[3].Big() raw, err := json.Marshal(ethLog) if err != nil { - return []VatMoveModel{}, err + return []interface{}{}, err } models = append(models, VatMoveModel{ diff --git a/pkg/transformers/vat_move/converter_test.go b/pkg/transformers/vat_move/converter_test.go index b4246865..c712cbd9 100644 --- a/pkg/transformers/vat_move/converter_test.go +++ b/pkg/transformers/vat_move/converter_test.go @@ -24,18 +24,20 @@ import ( ) var _ = Describe("Vat move converter", func() { - It("returns err if logs are missing topics", func() { - converter := vat_move.VatMoveConverter{} - badLog := types.Log{} + var converter vat_move.VatMoveConverter + BeforeEach(func() { + converter = vat_move.VatMoveConverter{} + }) + + It("returns err if logs are missing topics", func() { + badLog := types.Log{} _, err := converter.ToModels([]types.Log{badLog}) Expect(err).To(HaveOccurred()) }) It("converts a log to a model", func() { - converter := vat_move.VatMoveConverter{} - models, err := converter.ToModels([]types.Log{test_data.EthVatMoveLog}) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/transformers/vat_move/repository.go b/pkg/transformers/vat_move/repository.go index 821c36d5..91928ae4 100644 --- a/pkg/transformers/vat_move/repository.go +++ b/pkg/transformers/vat_move/repository.go @@ -15,33 +15,28 @@ package vat_move import ( + "fmt" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" ) -type Repository interface { - Create(headerID int64, models []VatMoveModel) error - MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) - MarkHeaderChecked(headerID int64) error -} - type VatMoveRepository struct { db *postgres.DB } -func NewVatMoveRepository(db *postgres.DB) VatMoveRepository { - return VatMoveRepository{ - db: db, - } -} - -func (repository VatMoveRepository) Create(headerID int64, models []VatMoveModel) error { +func (repository VatMoveRepository) Create(headerID int64, models []interface{}) error { tx, err := repository.db.Begin() if err != nil { return err } - for _, vatMove := range models { + for _, model := range models { + vatMove, ok := model.(VatMoveModel) + if !ok { + tx.Rollback() + return fmt.Errorf("model of type %T, not %T", model, VatMoveModel{}) + } + _, err = tx.Exec( `INSERT INTO maker.vat_move (header_id, src, dst, rad, tx_idx, raw_log) VALUES ($1, $2, $3, $4::NUMERIC, $5, $6)`, @@ -94,3 +89,7 @@ func (repository VatMoveRepository) MarkHeaderChecked(headerID int64) error { UPDATE SET vat_move_checked = $2`, headerID, true) return err } + +func (repository *VatMoveRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/vat_move/repository_test.go b/pkg/transformers/vat_move/repository_test.go index 6333f80b..1855ea83 100644 --- a/pkg/transformers/vat_move/repository_test.go +++ b/pkg/transformers/vat_move/repository_test.go @@ -16,9 +16,9 @@ package vat_move_test import ( "database/sql" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "math/rand" "github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" @@ -38,7 +38,8 @@ var _ = Describe("Vat Move", func() { db = test_config.NewTestDB(core.Node{}) test_config.CleanTestDB(db) headerRepository = repositories.NewHeaderRepository(db) - vatMoveRepository = vat_move.NewVatMoveRepository(db) + vatMoveRepository = vat_move.VatMoveRepository{} + vatMoveRepository.SetDB(db) }) Describe("Create", func() { @@ -48,7 +49,7 @@ var _ = Describe("Vat Move", func() { BeforeEach(func() { headerID, err = headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) Expect(err).NotTo(HaveOccurred()) - err = vatMoveRepository.Create(headerID, []vat_move.VatMoveModel{test_data.VatMoveModel}) + err = vatMoveRepository.Create(headerID, []interface{}{test_data.VatMoveModel}) Expect(err).NotTo(HaveOccurred()) }) @@ -71,7 +72,7 @@ var _ = Describe("Vat Move", func() { }) It("returns an error if insertion fails", func() { - err = vatMoveRepository.Create(headerID, []vat_move.VatMoveModel{test_data.VatMoveModel}) + err = vatMoveRepository.Create(headerID, []interface{}{test_data.VatMoveModel}) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) }) @@ -85,10 +86,16 @@ var _ = Describe("Vat Move", func() { Expect(err).To(HaveOccurred()) Expect(err).To(MatchError(sql.ErrNoRows)) }) + + It("Returns an error if model is of wrong type", func() { + err = vatMoveRepository.Create(headerID, []interface{}{test_data.WrongModel{}}) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("model of type")) + }) }) Describe("MissingHeaders", func() { - var eventBlockNumber = GinkgoRandomSeed() + var eventBlockNumber = rand.Int63() var startingBlockNumber = eventBlockNumber - 1 var endingBlockNumber = eventBlockNumber + 1 var outOfRangeBlockNumber = eventBlockNumber + 2 @@ -145,8 +152,9 @@ var _ = Describe("Vat Move", func() { _, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n)) Expect(err).NotTo(HaveOccurred()) } - vatMoveRepositoryTwo := vat_move.NewVatMoveRepository(dbTwo) - err := vatMoveRepository.Create(headerIDs[0], []vat_move.VatMoveModel{test_data.VatMoveModel}) + vatMoveRepositoryTwo := vat_move.VatMoveRepository{} + vatMoveRepositoryTwo.SetDB(dbTwo) + err := vatMoveRepository.Create(headerIDs[0], []interface{}{test_data.VatMoveModel}) Expect(err).NotTo(HaveOccurred()) nodeOneMissingHeaders, err := vatMoveRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) @@ -157,7 +165,6 @@ var _ = Describe("Vat Move", func() { Expect(err).NotTo(HaveOccurred()) Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers))) }) - }) Describe("MarkHeaderChecked", func() { diff --git a/pkg/transformers/vat_move/transformer.go b/pkg/transformers/vat_move/transformer.go deleted file mode 100644 index 5318143c..00000000 --- a/pkg/transformers/vat_move/transformer.go +++ /dev/null @@ -1,83 +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 vat_move - -import ( - "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 VatMoveTransformerInitializer struct { - Config shared.TransformerConfig -} - -func (initializer VatMoveTransformerInitializer) NewVatMoveTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { - converter := VatMoveConverter{} - fetcher := shared.NewFetcher(blockChain) - repository := NewVatMoveRepository(db) - return VatMoveTransformer{ - Config: initializer.Config, - Converter: converter, - Fetcher: fetcher, - Repository: repository, - } -} - -type VatMoveTransformer struct { - Config shared.TransformerConfig - Converter Converter - Fetcher shared.LogFetcher - Repository Repository -} - -func (transformer VatMoveTransformer) Execute() error { - missingHeaders, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber) - if err != nil { - return err - } - - log.Printf("Fetching vat move event logs for %d headers \n", len(missingHeaders)) - for _, header := range missingHeaders { - topics := [][]common.Hash{{common.HexToHash(shared.VatMoveSignature)}} - matchingLogs, err := transformer.Fetcher.FetchLogs(VatMoveConfig.ContractAddresses, topics, header.BlockNumber) - if err != nil { - return err - } - - if len(matchingLogs) < 1 { - err := transformer.Repository.MarkHeaderChecked(header.Id) - if err != nil { - return err - } - continue - } - - models, err := transformer.Converter.ToModels(matchingLogs) - if err != nil { - return err - } - - err = transformer.Repository.Create(header.Id, models) - if err != nil { - return err - } - } - return nil -} diff --git a/pkg/transformers/vat_move/transformer_test.go b/pkg/transformers/vat_move/transformer_test.go index 38371787..fa271e3b 100644 --- a/pkg/transformers/vat_move/transformer_test.go +++ b/pkg/transformers/vat_move/transformer_test.go @@ -21,18 +21,21 @@ import ( . "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/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" vat_move_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/vat_move" "github.com/vulcanize/vulcanizedb/pkg/transformers/vat_move" + "math/rand" ) var _ = Describe("Vat move transformer", func() { + var config = vat_move.VatMoveConfig var fetcher mocks.MockLogFetcher var converter vat_move_mocks.MockVatMoveConverter var repository vat_move_mocks.MockVatMoveRepository - var config = vat_move.VatMoveConfig + var transformer shared.Transformer var headerOne core.Header var headerTwo core.Header @@ -40,18 +43,22 @@ var _ = Describe("Vat move transformer", func() { fetcher = mocks.MockLogFetcher{} converter = vat_move_mocks.MockVatMoveConverter{} repository = vat_move_mocks.MockVatMoveRepository{} - headerOne = core.Header{Id: GinkgoRandomSeed(), BlockNumber: GinkgoRandomSeed()} - headerTwo = core.Header{Id: GinkgoRandomSeed(), BlockNumber: GinkgoRandomSeed()} - }) - - It("gets missing headers for block numbers specified in config", func() { - transformer := vat_move.VatMoveTransformer{ + headerOne = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + headerTwo = core.Header{Id: rand.Int63(), BlockNumber: rand.Int63()} + transformer = factories.Transformer{ Config: config, Converter: &converter, Fetcher: &fetcher, Repository: &repository, - } + }.NewTransformer(nil, nil) + }) + It("sets the blockchain and database", func() { + Expect(fetcher.SetBcCalled).To(BeTrue()) + Expect(repository.SetDbCalled).To(BeTrue()) + }) + + It("gets missing headers for block numbers specified in config", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) @@ -61,12 +68,6 @@ var _ = Describe("Vat move transformer", func() { It("returns error if repository returns error for missing headers", func() { repository.SetMissingHeadersError(fakes.FakeError) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Converter: &converter, - Fetcher: &fetcher, - Repository: &repository, - } err := transformer.Execute() @@ -76,12 +77,6 @@ var _ = Describe("Vat move transformer", func() { It("fetches logs for missing headers", func() { repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Fetcher: &fetcher, - Converter: &vat_move_mocks.MockVatMoveConverter{}, - Repository: &repository, - } err := transformer.Execute() @@ -97,12 +92,6 @@ var _ = Describe("Vat move transformer", func() { It("returns error if fetcher returns error", func() { fetcher.SetFetcherError(fakes.FakeError) repository.SetMissingHeaders([]core.Header{headerOne}) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Fetcher: &fetcher, - Converter: &converter, - Repository: &repository, - } err := transformer.Execute() @@ -113,12 +102,6 @@ var _ = Describe("Vat move transformer", func() { It("converts matching logs", func() { fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog}) repository.SetMissingHeaders([]core.Header{headerOne}) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Fetcher: &fetcher, - Converter: &converter, - Repository: &repository, - } err := transformer.Execute() @@ -130,12 +113,6 @@ var _ = Describe("Vat move transformer", func() { converter.SetConverterError(fakes.FakeError) fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog}) repository.SetMissingHeaders([]core.Header{headerOne}) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Fetcher: &fetcher, - Converter: &converter, - Repository: &repository, - } err := transformer.Execute() @@ -146,12 +123,6 @@ var _ = Describe("Vat move transformer", func() { It("marks header as checked even if no logs were returned", func() { repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) fetcher.SetFetchedLogs([]types.Log{}) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Converter: &converter, - Fetcher: &fetcher, - Repository: &repository, - } err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) @@ -163,12 +134,6 @@ var _ = Describe("Vat move transformer", func() { repository.SetMissingHeaders([]core.Header{headerOne, headerTwo}) repository.SetCheckedHeaderError(fakes.FakeError) fetcher.SetFetchedLogs([]types.Log{}) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Converter: &converter, - Fetcher: &fetcher, - Repository: &repository, - } err := transformer.Execute() @@ -179,30 +144,18 @@ var _ = Describe("Vat move transformer", func() { It("persists vat move model", func() { fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog}) repository.SetMissingHeaders([]core.Header{headerOne}) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Fetcher: &fetcher, - Converter: &converter, - Repository: &repository, - } err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) Expect(repository.PassedHeaderID).To(Equal(headerOne.Id)) - Expect(repository.PassedModels).To(Equal([]vat_move.VatMoveModel{test_data.VatMoveModel})) + Expect(repository.PassedModels).To(Equal([]interface{}{test_data.VatMoveModel})) }) It("returns error if repository returns error for create", func() { fetcher.SetFetchedLogs([]types.Log{test_data.EthVatMoveLog}) repository.SetMissingHeaders([]core.Header{headerOne}) repository.SetCreateError(fakes.FakeError) - transformer := vat_move.VatMoveTransformer{ - Config: config, - Fetcher: &fetcher, - Converter: &converter, - Repository: &repository, - } err := transformer.Execute()