forked from cerc-io/ipld-eth-server
Use transformer factory for Price Feed events
This commit is contained in:
parent
bd428e752a
commit
47a3c35938
@ -14,5 +14,5 @@ mcd_flop = "0x6191C9b0086c2eBF92300cC507009b53996FbFFa"
|
||||
pep = "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975"
|
||||
pip = "0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc"
|
||||
pit = "0xe7cf3198787c9a4daac73371a38f29aaeeced87e"
|
||||
rep = "0xf88bbdc1e2718f8857f30a180076ec38d53cf296"
|
||||
rep = "0xf88bBDc1E2718F8857F30A180076ec38d53cf296"
|
||||
vat = "0xcd726790550afcd77e9a7a47e86a3f9010af126b"
|
@ -15,5 +15,5 @@ mcd_flop = "0x6191C9b0086c2eBF92300cC507009b53996FbFFa"
|
||||
pep = "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975"
|
||||
pip = "0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc"
|
||||
pit = "0xe7cf3198787c9a4daac73371a38f29aaeeced87e"
|
||||
rep = "0xf88bbdc1e2718f8857f30a180076ec38d53cf296"
|
||||
rep = "0xf88bBDc1E2718F8857F30A180076ec38d53cf296"
|
||||
vat = "0xcd726790550afcd77e9a7a47e86a3f9010af126b"
|
@ -20,7 +20,9 @@ import (
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/factories"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
|
||||
"github.com/vulcanize/vulcanizedb/test_config"
|
||||
)
|
||||
|
||||
@ -43,13 +45,18 @@ var _ = Describe("Price feeds transformer", func() {
|
||||
blockNumber := int64(8763054)
|
||||
err := persistHeader(db, blockNumber)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
config := price_feeds.IPriceFeedConfig{
|
||||
ContractAddresses: []string{"0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc"},
|
||||
StartingBlockNumber: blockNumber,
|
||||
EndingBlockNumber: blockNumber,
|
||||
config := price_feeds.PriceFeedConfig
|
||||
config.ContractAddresses = []string{shared.PipContractAddress}
|
||||
config.StartingBlockNumber = blockNumber
|
||||
config.EndingBlockNumber = blockNumber
|
||||
|
||||
transformerInitializer := factories.Transformer{
|
||||
Config: config,
|
||||
Converter: &price_feeds.PriceFeedConverter{},
|
||||
Repository: &price_feeds.PriceFeedRepository{},
|
||||
Fetcher: &shared.Fetcher{},
|
||||
}
|
||||
transformerInitializer := price_feeds.PriceFeedTransformerInitializer{Config: config}
|
||||
transformer := transformerInitializer.NewPriceFeedTransformer(db, blockChain)
|
||||
transformer := transformerInitializer.NewTransformer(db, blockChain)
|
||||
|
||||
err = transformer.Execute()
|
||||
|
||||
@ -65,13 +72,18 @@ var _ = Describe("Price feeds transformer", func() {
|
||||
blockNumber := int64(8763059)
|
||||
err := persistHeader(db, blockNumber)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
config := price_feeds.IPriceFeedConfig{
|
||||
ContractAddresses: []string{"0xB1997239Cfc3d15578A3a09730f7f84A90BB4975"},
|
||||
StartingBlockNumber: blockNumber,
|
||||
EndingBlockNumber: blockNumber,
|
||||
config := price_feeds.PriceFeedConfig
|
||||
config.ContractAddresses = []string{shared.PepContractAddress}
|
||||
config.StartingBlockNumber = blockNumber
|
||||
config.EndingBlockNumber = blockNumber
|
||||
|
||||
transformerInitializer := factories.Transformer{
|
||||
Config: config,
|
||||
Converter: &price_feeds.PriceFeedConverter{},
|
||||
Repository: &price_feeds.PriceFeedRepository{},
|
||||
Fetcher: &shared.Fetcher{},
|
||||
}
|
||||
transformerInitializer := price_feeds.PriceFeedTransformerInitializer{Config: config}
|
||||
transformer := transformerInitializer.NewPriceFeedTransformer(db, blockChain)
|
||||
transformer := transformerInitializer.NewTransformer(db, blockChain)
|
||||
|
||||
err = transformer.Execute()
|
||||
|
||||
@ -87,13 +99,18 @@ var _ = Describe("Price feeds transformer", func() {
|
||||
blockNumber := int64(8763062)
|
||||
err := persistHeader(db, blockNumber)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
config := price_feeds.IPriceFeedConfig{
|
||||
ContractAddresses: []string{"0xf88bBDc1E2718F8857F30A180076ec38d53cf296"},
|
||||
StartingBlockNumber: blockNumber,
|
||||
EndingBlockNumber: blockNumber,
|
||||
config := price_feeds.PriceFeedConfig
|
||||
config.ContractAddresses = []string{shared.RepContractAddress}
|
||||
config.StartingBlockNumber = blockNumber
|
||||
config.EndingBlockNumber = blockNumber
|
||||
|
||||
transformerInitializer := factories.Transformer{
|
||||
Config: config,
|
||||
Converter: &price_feeds.PriceFeedConverter{},
|
||||
Repository: &price_feeds.PriceFeedRepository{},
|
||||
Fetcher: &shared.Fetcher{},
|
||||
}
|
||||
transformerInitializer := price_feeds.PriceFeedTransformerInitializer{Config: config}
|
||||
transformer := transformerInitializer.NewPriceFeedTransformer(db, blockChain)
|
||||
transformer := transformerInitializer.NewTransformer(db, blockChain)
|
||||
|
||||
err = transformer.Execute()
|
||||
|
||||
|
@ -16,20 +16,15 @@ package price_feeds
|
||||
|
||||
import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
|
||||
|
||||
var ()
|
||||
|
||||
type IPriceFeedConfig struct {
|
||||
ContractAddresses []string
|
||||
StartingBlockNumber int64
|
||||
EndingBlockNumber int64
|
||||
}
|
||||
|
||||
var PriceFeedConfig = IPriceFeedConfig{
|
||||
var PriceFeedConfig = shared.SingleTransformerConfig{
|
||||
TransformerName: shared.PriceFeedLabel,
|
||||
ContractAddresses: []string{
|
||||
shared.PepContractAddress,
|
||||
shared.PipContractAddress,
|
||||
shared.RepContractAddress,
|
||||
},
|
||||
ContractAbi: shared.MedianizerABI,
|
||||
Topic: shared.LogValueSignature,
|
||||
StartingBlockNumber: 0,
|
||||
EndingBlockNumber: 10000000,
|
||||
}
|
||||
|
@ -20,14 +20,11 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
type Converter interface {
|
||||
ToModels(logs []types.Log, headerID int64) ([]PriceFeedModel, error)
|
||||
}
|
||||
|
||||
type PriceFeedConverter struct{}
|
||||
|
||||
func (converter PriceFeedConverter) ToModels(logs []types.Log, headerID int64) (results []PriceFeedModel, err error) {
|
||||
for _, log := range logs {
|
||||
func (converter PriceFeedConverter) ToModels(ethLogs []types.Log) ([]interface{}, error) {
|
||||
var results []interface{}
|
||||
for _, log := range ethLogs {
|
||||
raw, err := json.Marshal(log)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -42,5 +39,5 @@ func (converter PriceFeedConverter) ToModels(logs []types.Log, headerID int64) (
|
||||
}
|
||||
results = append(results, model)
|
||||
}
|
||||
return results, err
|
||||
return results, nil
|
||||
}
|
||||
|
@ -26,9 +26,8 @@ import (
|
||||
var _ = Describe("Price feed Converter", func() {
|
||||
It("converts a log to a price feed model", func() {
|
||||
converter := price_feeds.PriceFeedConverter{}
|
||||
headerID := int64(123)
|
||||
|
||||
models, err := converter.ToModels([]types.Log{test_data.EthPriceFeedLog}, headerID)
|
||||
models, err := converter.ToModels([]types.Log{test_data.EthPriceFeedLog})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(len(models)).To(Equal(1))
|
||||
|
@ -1,57 +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 price_feeds
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
|
||||
)
|
||||
|
||||
type IPriceFeedFetcher interface {
|
||||
FetchLogValues(blockNumber int64) ([]types.Log, error)
|
||||
}
|
||||
|
||||
type PriceFeedFetcher struct {
|
||||
blockChain core.BlockChain
|
||||
contractAddresses []string
|
||||
}
|
||||
|
||||
func NewPriceFeedFetcher(blockChain core.BlockChain, contractAddresses []string) PriceFeedFetcher {
|
||||
return PriceFeedFetcher{
|
||||
blockChain: blockChain,
|
||||
contractAddresses: contractAddresses,
|
||||
}
|
||||
}
|
||||
|
||||
func (fetcher PriceFeedFetcher) FetchLogValues(blockNumber int64) ([]types.Log, error) {
|
||||
var addresses []common.Address
|
||||
for _, addr := range fetcher.contractAddresses {
|
||||
addresses = append(addresses, common.HexToAddress(addr))
|
||||
}
|
||||
n := big.NewInt(blockNumber)
|
||||
query := ethereum.FilterQuery{
|
||||
FromBlock: n,
|
||||
ToBlock: n,
|
||||
Addresses: addresses,
|
||||
Topics: [][]common.Hash{{common.HexToHash(shared.LogValueSignature)}},
|
||||
}
|
||||
return fetcher.blockChain.GetEthLogsWithCustomQuery(query)
|
||||
}
|
@ -1,65 +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 price_feeds_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/fakes"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
|
||||
)
|
||||
|
||||
var _ = Describe("Price fetcher", func() {
|
||||
It("gets log value events from price feed medianizers", func() {
|
||||
mockBlockChain := fakes.NewMockBlockChain()
|
||||
mockBlockChain.SetGetEthLogsWithCustomQueryReturnLogs([]types.Log{{}})
|
||||
contractAddresses := []string{"pep-contract-address", "pip-contract-address", "rep-contract-address"}
|
||||
fetcher := price_feeds.NewPriceFeedFetcher(mockBlockChain, contractAddresses)
|
||||
blockNumber := int64(100)
|
||||
|
||||
_, err := fetcher.FetchLogValues(blockNumber)
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var expectedAddresses []common.Address
|
||||
for _, address := range contractAddresses {
|
||||
expectedAddresses = append(expectedAddresses, common.HexToAddress(address))
|
||||
}
|
||||
expectedQuery := ethereum.FilterQuery{
|
||||
FromBlock: big.NewInt(blockNumber),
|
||||
ToBlock: big.NewInt(blockNumber),
|
||||
Addresses: expectedAddresses,
|
||||
Topics: [][]common.Hash{{common.HexToHash(shared.LogValueSignature)}},
|
||||
}
|
||||
mockBlockChain.AssertGetEthLogsWithCustomQueryCalledWith(expectedQuery)
|
||||
})
|
||||
|
||||
It("returns error if getting logs fails", func() {
|
||||
mockBlockChain := fakes.NewMockBlockChain()
|
||||
mockBlockChain.SetGetEthLogsWithCustomQueryErr(fakes.FakeError)
|
||||
fetcher := price_feeds.NewPriceFeedFetcher(mockBlockChain, []string{"contract-address"})
|
||||
|
||||
_, err := fetcher.FetchLogValues(100)
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(fakes.FakeError))
|
||||
})
|
||||
})
|
@ -15,32 +15,29 @@
|
||||
package price_feeds
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
|
||||
)
|
||||
|
||||
type IPriceFeedRepository interface {
|
||||
Create(headerID int64, models []PriceFeedModel) error
|
||||
MarkHeaderChecked(headerID int64) error
|
||||
MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error)
|
||||
}
|
||||
|
||||
type PriceFeedRepository struct {
|
||||
db *postgres.DB
|
||||
}
|
||||
|
||||
func NewPriceFeedRepository(db *postgres.DB) PriceFeedRepository {
|
||||
return PriceFeedRepository{db: db}
|
||||
}
|
||||
|
||||
func (repository PriceFeedRepository) Create(headerID int64, models []PriceFeedModel) error {
|
||||
func (repository PriceFeedRepository) Create(headerID int64, models []interface{}) error {
|
||||
tx, err := repository.db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, model := range models {
|
||||
priceUpdate, ok := model.(PriceFeedModel)
|
||||
if !ok {
|
||||
tx.Rollback()
|
||||
return fmt.Errorf("model of type %T, not %T", model, PriceFeedModel{})
|
||||
}
|
||||
|
||||
_, err = tx.Exec(`INSERT INTO maker.price_feeds (block_number, header_id, medianizer_address, usd_value, log_idx, tx_idx, raw_log)
|
||||
VALUES ($1, $2, $3, $4::NUMERIC, $5, $6, $7)`, model.BlockNumber, headerID, model.MedianizerAddress, model.UsdValue, model.LogIndex, model.TransactionIndex, model.Raw)
|
||||
VALUES ($1, $2, $3, $4::NUMERIC, $5, $6, $7)`, priceUpdate.BlockNumber, headerID, priceUpdate.MedianizerAddress, priceUpdate.UsdValue, priceUpdate.LogIndex, priceUpdate.TransactionIndex, priceUpdate.Raw)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
@ -81,3 +78,7 @@ func (repository PriceFeedRepository) MissingHeaders(startingBlockNumber, ending
|
||||
)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (repository *PriceFeedRepository) SetDB(db *postgres.DB) {
|
||||
repository.db = db
|
||||
}
|
||||
|
@ -35,14 +35,15 @@ var _ = Describe("Price feeds repository", func() {
|
||||
db *postgres.DB
|
||||
err error
|
||||
headerRepository datastore.HeaderRepository
|
||||
priceFeedRepository price_feeds.IPriceFeedRepository
|
||||
priceFeedRepository price_feeds.PriceFeedRepository
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
db = test_config.NewTestDB(core.Node{})
|
||||
test_config.CleanTestDB(db)
|
||||
headerRepository = repositories.NewHeaderRepository(db)
|
||||
priceFeedRepository = price_feeds.NewPriceFeedRepository(db)
|
||||
priceFeedRepository = price_feeds.PriceFeedRepository{}
|
||||
priceFeedRepository.SetDB(db)
|
||||
})
|
||||
|
||||
Describe("Create", func() {
|
||||
@ -54,7 +55,7 @@ var _ = Describe("Price feeds repository", func() {
|
||||
})
|
||||
|
||||
It("persists a price feed update", func() {
|
||||
err = priceFeedRepository.Create(headerID, []price_feeds.PriceFeedModel{test_data.PriceFeedModel})
|
||||
err = priceFeedRepository.Create(headerID, []interface{}{test_data.PriceFeedModel})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var dbPriceFeedUpdate price_feeds.PriceFeedModel
|
||||
@ -69,7 +70,7 @@ var _ = Describe("Price feeds repository", func() {
|
||||
})
|
||||
|
||||
It("marks headerID as checked for price feed logs", func() {
|
||||
err = priceFeedRepository.Create(headerID, []price_feeds.PriceFeedModel{test_data.PriceFeedModel})
|
||||
err = priceFeedRepository.Create(headerID, []interface{}{test_data.PriceFeedModel})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var headerChecked bool
|
||||
@ -82,7 +83,7 @@ var _ = Describe("Price feeds repository", func() {
|
||||
_, err = db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerID)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = priceFeedRepository.Create(headerID, []price_feeds.PriceFeedModel{test_data.PriceFeedModel})
|
||||
err = priceFeedRepository.Create(headerID, []interface{}{test_data.PriceFeedModel})
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
var headerChecked bool
|
||||
@ -92,17 +93,17 @@ var _ = Describe("Price feeds repository", func() {
|
||||
})
|
||||
|
||||
It("does not duplicate price feed updates", func() {
|
||||
err = priceFeedRepository.Create(headerID, []price_feeds.PriceFeedModel{test_data.PriceFeedModel})
|
||||
err = priceFeedRepository.Create(headerID, []interface{}{test_data.PriceFeedModel})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
err = priceFeedRepository.Create(headerID, []price_feeds.PriceFeedModel{test_data.PriceFeedModel})
|
||||
err = priceFeedRepository.Create(headerID, []interface{}{test_data.PriceFeedModel})
|
||||
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint"))
|
||||
})
|
||||
|
||||
It("removes price feed if corresponding header is deleted", func() {
|
||||
err = priceFeedRepository.Create(headerID, []price_feeds.PriceFeedModel{test_data.PriceFeedModel})
|
||||
err = priceFeedRepository.Create(headerID, []interface{}{test_data.PriceFeedModel})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
_, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID)
|
||||
@ -113,6 +114,12 @@ var _ = Describe("Price feeds repository", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err).To(MatchError(sql.ErrNoRows))
|
||||
})
|
||||
|
||||
It("returns an error if model is of wrong type", func() {
|
||||
err = priceFeedRepository.Create(headerID, []interface{}{test_data.WrongModel{}})
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("model of type"))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("MarkHeaderChecked", func() {
|
||||
@ -200,7 +207,8 @@ var _ = Describe("Price feeds repository", func() {
|
||||
_, err = headerRepositoryTwo.CreateOrUpdateHeader(fakes.GetFakeHeader(n))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
priceFeedRepositoryTwo := price_feeds.NewPriceFeedRepository(dbTwo)
|
||||
priceFeedRepositoryTwo := price_feeds.PriceFeedRepository{}
|
||||
priceFeedRepositoryTwo.SetDB(dbTwo)
|
||||
err := priceFeedRepository.MarkHeaderChecked(headerIDs[0])
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
|
@ -1,75 +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 price_feeds
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
|
||||
)
|
||||
|
||||
type PriceFeedTransformerInitializer struct {
|
||||
Config IPriceFeedConfig
|
||||
}
|
||||
|
||||
func (initializer PriceFeedTransformerInitializer) NewPriceFeedTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer {
|
||||
converter := PriceFeedConverter{}
|
||||
fetcher := NewPriceFeedFetcher(blockChain, initializer.Config.ContractAddresses)
|
||||
repository := NewPriceFeedRepository(db)
|
||||
return PriceFeedTransformer{
|
||||
Config: initializer.Config,
|
||||
Converter: converter,
|
||||
Fetcher: fetcher,
|
||||
Repository: repository,
|
||||
}
|
||||
}
|
||||
|
||||
type PriceFeedTransformer struct {
|
||||
Config IPriceFeedConfig
|
||||
Converter Converter
|
||||
Fetcher IPriceFeedFetcher
|
||||
Repository IPriceFeedRepository
|
||||
}
|
||||
|
||||
func (transformer PriceFeedTransformer) Execute() error {
|
||||
headers, err := transformer.Repository.MissingHeaders(transformer.Config.StartingBlockNumber, transformer.Config.EndingBlockNumber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("Fetching price feed event logs for %d headers \n", len(headers))
|
||||
for _, header := range headers {
|
||||
logs, err := transformer.Fetcher.FetchLogValues(header.BlockNumber)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(logs) < 1 {
|
||||
err := transformer.Repository.MarkHeaderChecked(header.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
models, err := transformer.Converter.ToModels(logs, header.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = transformer.Repository.Create(header.Id, models)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -19,39 +19,57 @@ import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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/price_feeds"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
|
||||
price_feeds_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/price_feeds"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
var _ = Describe("Price feed transformer", func() {
|
||||
It("gets missing headers for price feeds", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Config: price_feeds.PriceFeedConfig,
|
||||
Converter: mockConverter,
|
||||
Fetcher: &price_feeds_mocks.MockPriceFeedFetcher{},
|
||||
Repository: mockRepository,
|
||||
}
|
||||
var (
|
||||
config = price_feeds.PriceFeedConfig
|
||||
fetcher mocks.MockLogFetcher
|
||||
converter mocks.MockConverter
|
||||
repository mocks.MockRepository
|
||||
transformer shared.Transformer
|
||||
headerOne core.Header
|
||||
headerTwo core.Header
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
fetcher = mocks.MockLogFetcher{}
|
||||
converter = mocks.MockConverter{}
|
||||
repository = mocks.MockRepository{}
|
||||
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 db", func() {
|
||||
Expect(fetcher.SetBcCalled).To(BeTrue())
|
||||
Expect(repository.SetDbCalled).To(BeTrue())
|
||||
})
|
||||
|
||||
It("gets missing headers for price feeds", func() {
|
||||
err := transformer.Execute()
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockRepository.AssertMissingHeadersCalledwith(price_feeds.PriceFeedConfig.StartingBlockNumber, price_feeds.PriceFeedConfig.EndingBlockNumber)
|
||||
Expect(repository.PassedStartingBlockNumber).To(Equal(config.StartingBlockNumber))
|
||||
Expect(repository.PassedEndingBlockNumber).To(Equal(config.EndingBlockNumber))
|
||||
})
|
||||
|
||||
It("returns error is missing headers call returns err", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
mockRepository.SetMissingHeadersErr(fakes.FakeError)
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Converter: mockConverter,
|
||||
Fetcher: &price_feeds_mocks.MockPriceFeedFetcher{},
|
||||
Repository: mockRepository,
|
||||
}
|
||||
repository.SetMissingHeadersError(fakes.FakeError)
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
@ -60,35 +78,19 @@ var _ = Describe("Price feed transformer", func() {
|
||||
})
|
||||
|
||||
It("fetches logs for missing headers", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
blockNumberOne := int64(1)
|
||||
blockNumberTwo := int64(2)
|
||||
mockRepository.SetMissingHeaders([]core.Header{{BlockNumber: blockNumberOne}, {BlockNumber: blockNumberTwo}})
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Converter: mockConverter,
|
||||
Fetcher: mockFetcher,
|
||||
Repository: mockRepository,
|
||||
}
|
||||
repository.SetMissingHeaders([]core.Header{headerOne, headerTwo})
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockFetcher.AssertFetchLogValuesCalledWith([]int64{blockNumberOne, blockNumberTwo})
|
||||
Expect(fetcher.FetchedContractAddresses).To(Equal([][]string{config.ContractAddresses, config.ContractAddresses}))
|
||||
Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(config.Topic)}}))
|
||||
Expect(fetcher.FetchedBlocks).To(Equal([]int64{headerOne.BlockNumber, headerTwo.BlockNumber}))
|
||||
})
|
||||
|
||||
It("returns err if fetcher returns err", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
mockRepository.SetMissingHeaders([]core.Header{{BlockNumber: 1}})
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
mockFetcher.SetReturnErr(fakes.FakeError)
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Converter: mockConverter,
|
||||
Fetcher: mockFetcher,
|
||||
Repository: mockRepository,
|
||||
}
|
||||
repository.SetMissingHeaders([]core.Header{headerOne})
|
||||
fetcher.SetFetcherError(fakes.FakeError)
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
@ -97,34 +99,17 @@ var _ = Describe("Price feed transformer", func() {
|
||||
})
|
||||
|
||||
It("marks header checked if no logs returned", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
headerID := int64(123)
|
||||
mockRepository.SetMissingHeaders([]core.Header{{Id: headerID}})
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
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 := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
mockRepository.SetMissingHeaders([]core.Header{{Id: int64(123)}})
|
||||
mockRepository.SetMarkHeaderCheckedErr(fakes.FakeError)
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Converter: mockConverter,
|
||||
Fetcher: mockFetcher,
|
||||
Repository: mockRepository,
|
||||
}
|
||||
repository.SetMissingHeaders([]core.Header{headerOne})
|
||||
repository.SetMarkHeaderCheckedError(fakes.FakeError)
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
@ -133,38 +118,19 @@ var _ = Describe("Price feed transformer", func() {
|
||||
})
|
||||
|
||||
It("converts log to a model", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
mockFetcher.SetReturnLogs([]types.Log{test_data.EthPriceFeedLog})
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
headerID := int64(11111)
|
||||
mockRepository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: headerID}})
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Fetcher: mockFetcher,
|
||||
Converter: mockConverter,
|
||||
Repository: mockRepository,
|
||||
}
|
||||
fetcher.SetFetchedLogs([]types.Log{test_data.EthPriceFeedLog})
|
||||
repository.SetMissingHeaders([]core.Header{headerOne})
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(mockConverter.PassedHeaderID).To(Equal(headerID))
|
||||
Expect(mockConverter.PassedLogs).To(Equal([]types.Log{test_data.EthPriceFeedLog}))
|
||||
Expect(converter.PassedLogs).To(Equal([]types.Log{test_data.EthPriceFeedLog}))
|
||||
})
|
||||
|
||||
It("returns err if converter returns err", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockConverter.SetConverterErr(fakes.FakeError)
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
mockFetcher.SetReturnLogs([]types.Log{test_data.EthPriceFeedLog})
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
headerID := int64(11111)
|
||||
mockRepository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: headerID}})
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Fetcher: mockFetcher,
|
||||
Converter: mockConverter,
|
||||
Repository: mockRepository,
|
||||
}
|
||||
converter.SetConverterError(fakes.FakeError)
|
||||
fetcher.SetFetchedLogs([]types.Log{test_data.EthPriceFeedLog})
|
||||
repository.SetMissingHeaders([]core.Header{headerOne})
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
@ -173,36 +139,22 @@ var _ = Describe("Price feed transformer", func() {
|
||||
})
|
||||
|
||||
It("persists model converted from log", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
headerID := int64(11111)
|
||||
mockRepository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: headerID}})
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
mockFetcher.SetReturnLogs([]types.Log{test_data.EthPriceFeedLog})
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Converter: mockConverter,
|
||||
Fetcher: mockFetcher,
|
||||
Repository: mockRepository,
|
||||
}
|
||||
converter.SetReturnModels([]interface{}{test_data.PriceFeedModel})
|
||||
repository.SetMissingHeaders([]core.Header{headerOne})
|
||||
fetcher.SetFetchedLogs([]types.Log{test_data.EthPriceFeedLog})
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
mockRepository.AssertCreateCalledWith(headerID, []price_feeds.PriceFeedModel{test_data.PriceFeedModel})
|
||||
Expect(repository.PassedHeaderID).To(Equal(headerOne.Id))
|
||||
Expect(len(repository.PassedModels)).To(Equal(1))
|
||||
Expect(repository.PassedModels[0]).To(Equal(test_data.PriceFeedModel))
|
||||
})
|
||||
|
||||
It("returns error if creating price feed update returns error", func() {
|
||||
mockConverter := &price_feeds_mocks.MockPriceFeedConverter{}
|
||||
mockRepository := &price_feeds_mocks.MockPriceFeedRepository{}
|
||||
mockRepository.SetMissingHeaders([]core.Header{{BlockNumber: 1, Id: 2}})
|
||||
mockRepository.SetCreateErr(fakes.FakeError)
|
||||
mockFetcher := &price_feeds_mocks.MockPriceFeedFetcher{}
|
||||
mockFetcher.SetReturnLogs([]types.Log{{}})
|
||||
transformer := price_feeds.PriceFeedTransformer{
|
||||
Converter: mockConverter,
|
||||
Fetcher: mockFetcher,
|
||||
Repository: mockRepository,
|
||||
}
|
||||
repository.SetMissingHeaders([]core.Header{headerOne})
|
||||
repository.SetCreateError(fakes.FakeError)
|
||||
fetcher.SetFetchedLogs([]types.Log{{}})
|
||||
|
||||
err := transformer.Execute()
|
||||
|
||||
|
@ -46,7 +46,7 @@ var (
|
||||
PepContractAddress = getContractValue("contract.pep", "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975")
|
||||
PipContractAddress = getContractValue("contract.pip", "0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc")
|
||||
PitContractAddress = getContractValue("contract.pit", "0xe7cf3198787c9a4daac73371a38f29aaeeced87e")
|
||||
RepContractAddress = getContractValue("contract.rep", "0xf88bbdc1e2718f8857f30a180076ec38d53cf296")
|
||||
RepContractAddress = getContractValue("contract.rep", "0xf88bBDc1E2718F8857F30A180076ec38d53cf296")
|
||||
VatContractAddress = getContractValue("contract.vat", "0xcd726790550afcd77e9a7a47e86a3f9010af126b")
|
||||
VowContractAddress = getContractValue("contract.vow", "0x3728e9777B2a0a611ee0F89e00E01044ce4736d1")
|
||||
|
||||
|
@ -1,37 +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 price_feeds
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
|
||||
)
|
||||
|
||||
type MockPriceFeedConverter struct {
|
||||
converterErr error
|
||||
PassedLogs []types.Log
|
||||
PassedHeaderID int64
|
||||
}
|
||||
|
||||
func (converter *MockPriceFeedConverter) ToModels(logs []types.Log, headerID int64) ([]price_feeds.PriceFeedModel, error) {
|
||||
converter.PassedLogs = logs
|
||||
converter.PassedHeaderID = headerID
|
||||
return []price_feeds.PriceFeedModel{test_data.PriceFeedModel}, converter.converterErr
|
||||
}
|
||||
|
||||
func (converter *MockPriceFeedConverter) SetConverterErr(e error) {
|
||||
converter.converterErr = e
|
||||
}
|
@ -1,43 +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 price_feeds
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
type MockPriceFeedFetcher struct {
|
||||
passedBlockNumbers []int64
|
||||
returnErr error
|
||||
returnLogs []types.Log
|
||||
}
|
||||
|
||||
func (fetcher *MockPriceFeedFetcher) SetReturnErr(err error) {
|
||||
fetcher.returnErr = err
|
||||
}
|
||||
|
||||
func (fetcher *MockPriceFeedFetcher) SetReturnLogs(logs []types.Log) {
|
||||
fetcher.returnLogs = logs
|
||||
}
|
||||
|
||||
func (fetcher *MockPriceFeedFetcher) FetchLogValues(blockNumber int64) ([]types.Log, error) {
|
||||
fetcher.passedBlockNumbers = append(fetcher.passedBlockNumbers, blockNumber)
|
||||
return fetcher.returnLogs, fetcher.returnErr
|
||||
}
|
||||
|
||||
func (fetcher *MockPriceFeedFetcher) AssertFetchLogValuesCalledWith(blockNumbers []int64) {
|
||||
Expect(fetcher.passedBlockNumbers).To(Equal(blockNumbers))
|
||||
}
|
@ -1,81 +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 price_feeds
|
||||
|
||||
import (
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||
"github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds"
|
||||
)
|
||||
|
||||
type MockPriceFeedRepository struct {
|
||||
createErr error
|
||||
createPassedHeaderID int64
|
||||
markHeaderCheckedErr error
|
||||
markHeaderCheckedPassedHeaderID int64
|
||||
missingHeaders []core.Header
|
||||
missingHeadersErr error
|
||||
passedEndingBlockNumber int64
|
||||
passedModels []price_feeds.PriceFeedModel
|
||||
passedStartingBlockNumber int64
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) SetCreateErr(err error) {
|
||||
repository.createErr = err
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) SetMarkHeaderCheckedErr(err error) {
|
||||
repository.markHeaderCheckedErr = err
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) SetMissingHeadersErr(err error) {
|
||||
repository.missingHeadersErr = err
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) SetMissingHeaders(headers []core.Header) {
|
||||
repository.missingHeaders = headers
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) Create(headerID int64, models []price_feeds.PriceFeedModel) error {
|
||||
repository.createPassedHeaderID = headerID
|
||||
repository.passedModels = models
|
||||
return repository.createErr
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) MarkHeaderChecked(headerID int64) error {
|
||||
repository.markHeaderCheckedPassedHeaderID = headerID
|
||||
return repository.markHeaderCheckedErr
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
|
||||
repository.passedStartingBlockNumber = startingBlockNumber
|
||||
repository.passedEndingBlockNumber = endingBlockNumber
|
||||
return repository.missingHeaders, repository.missingHeadersErr
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) AssertCreateCalledWith(headerID int64, models []price_feeds.PriceFeedModel) {
|
||||
Expect(repository.createPassedHeaderID).To(Equal(headerID))
|
||||
Expect(repository.passedModels).To(Equal(models))
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) AssertMarkHeaderCheckedCalledWith(headerID int64) {
|
||||
Expect(repository.markHeaderCheckedPassedHeaderID).To(Equal(headerID))
|
||||
}
|
||||
|
||||
func (repository *MockPriceFeedRepository) AssertMissingHeadersCalledwith(startingBlockNumber, endingBlockNumber int64) {
|
||||
Expect(repository.passedStartingBlockNumber).To(Equal(startingBlockNumber))
|
||||
Expect(repository.passedEndingBlockNumber).To(Equal(endingBlockNumber))
|
||||
}
|
@ -109,7 +109,13 @@ var (
|
||||
Fetcher: &shared.Fetcher{},
|
||||
}.NewTransformer
|
||||
|
||||
PriceFeedTransformerInitializer = price_feeds.PriceFeedTransformerInitializer{Config: price_feeds.PriceFeedConfig}.NewPriceFeedTransformer
|
||||
PriceFeedTransformerInitializer = factories.Transformer{
|
||||
Config: price_feeds.PriceFeedConfig,
|
||||
Converter: &price_feeds.PriceFeedConverter{},
|
||||
Repository: &price_feeds.PriceFeedRepository{},
|
||||
Fetcher: &shared.Fetcher{},
|
||||
}.NewTransformer
|
||||
|
||||
TendTransformerInitializer = factories.Transformer{
|
||||
Config: tend.TendConfig,
|
||||
Converter: &tend.TendConverter{},
|
||||
|
Loading…
Reference in New Issue
Block a user