Merge pull request #73 from 8thlight/transformer-refactoring

Transformer factory evaluation
This commit is contained in:
Takayuki Goto 2018-10-23 13:43:19 -05:00 committed by GitHub
commit f10bddf353
96 changed files with 1465 additions and 2101 deletions

View File

@ -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
}

View File

@ -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;

View File

@ -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,
}

View File

@ -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,

View File

@ -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))
})
})

View File

@ -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
}

View File

@ -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())

View File

@ -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
}

View File

@ -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()

View File

@ -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,
}

View File

@ -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,

View File

@ -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))
})
})

View File

@ -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
}

View File

@ -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())

View File

@ -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
}

View File

@ -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()

View File

@ -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,
}

View File

@ -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,

View File

@ -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))
})
})

View File

@ -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
}

View File

@ -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())

View File

@ -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
}

View File

@ -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()

View File

@ -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
}

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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())

View File

@ -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,
}

View File

@ -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 {

View File

@ -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))
})
})

View File

@ -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
}

View File

@ -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)))
})

View File

@ -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
}

View File

@ -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()

View File

@ -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,
}

View File

@ -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 {

View File

@ -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))
})
})

View File

@ -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
}

View File

@ -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())

View File

@ -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
}

View File

@ -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()

View File

@ -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,
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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))

View File

@ -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
}

View File

@ -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()

View File

@ -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"
)

View File

@ -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,

View File

@ -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
}

View File

@ -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,
}

View File

@ -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 {

View File

@ -28,7 +28,7 @@ var _ = Describe("Tend TendConverter", func() {
var converter tend.TendConverter
BeforeEach(func() {
converter = tend.NewTendConverter()
converter = tend.TendConverter{}
})
Describe("ToModels", func() {

View File

@ -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
}

View File

@ -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))

View File

@ -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
}

View File

@ -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()

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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) {

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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) {

View File

@ -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
}

View File

@ -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{}

View File

@ -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 {

View File

@ -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,
}

View File

@ -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 {

View File

@ -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())

View File

@ -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
}

View File

@ -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])

View File

@ -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
}

View File

@ -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()

View File

@ -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,
}

View File

@ -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{

View File

@ -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())

View File

@ -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
}

View File

@ -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() {

View File

@ -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
}

View File

@ -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()