Merge pull request #14 from 8thlight/pit-file

Pit file
This commit is contained in:
Rob Mulholand 2018-09-06 12:58:29 -05:00 committed by GitHub
commit ae6d184e6c
73 changed files with 2256 additions and 172 deletions

View File

@ -1,13 +1,14 @@
CREATE TABLE maker.frob ( CREATE TABLE maker.frob (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
header_id INTEGER NOT NULL REFERENCES headers (id) ON DELETE CASCADE, header_id INTEGER NOT NULL REFERENCES headers (id) ON DELETE CASCADE,
tx_idx INTEGER,
ilk bytea, ilk bytea,
lad bytea, urn bytea,
dink NUMERIC, dink NUMERIC,
dart NUMERIC, dart NUMERIC,
ink NUMERIC, ink NUMERIC,
art NUMERIC, art NUMERIC,
iart NUMERIC, iart NUMERIC,
tx_idx INTEGER NOT NUll,
raw_log JSONB,
UNIQUE (header_id, tx_idx) UNIQUE (header_id, tx_idx)
); );

View File

@ -0,0 +1,3 @@
DROP TABLE maker.pit_file_ilk;
DROP TABLE maker.pit_file_stability_fee;
DROP TABLE maker.pit_file_debt_ceiling;

View File

@ -0,0 +1,30 @@
CREATE TABLE maker.pit_file_ilk (
id SERIAL PRIMARY KEY,
header_id INTEGER NOT NULL REFERENCES headers (id) ON DELETE CASCADE,
ilk TEXT,
what TEXT,
data NUMERIC,
tx_idx INTEGER NOT NUll,
raw_log JSONB,
UNIQUE (header_id, tx_idx)
);
CREATE TABLE maker.pit_file_stability_fee (
id SERIAL PRIMARY KEY,
header_id INTEGER NOT NULL REFERENCES headers (id) ON DELETE CASCADE,
what TEXT,
data TEXT,
tx_idx INTEGER NOT NULL,
raw_log JSONB,
UNIQUE (header_id, tx_idx)
);
CREATE TABLE maker.pit_file_debt_ceiling (
id SERIAL PRIMARY KEY,
header_id INTEGER NOT NULL REFERENCES headers (id) ON DELETE CASCADE,
what TEXT,
data NUMERIC,
tx_idx INTEGER NOT NULL,
raw_log JSONB,
UNIQUE (header_id, tx_idx)
);

View File

@ -124,14 +124,15 @@ ALTER SEQUENCE maker.flip_kick_db_id_seq OWNED BY maker.flip_kick.db_id;
CREATE TABLE maker.frob ( CREATE TABLE maker.frob (
id integer NOT NULL, id integer NOT NULL,
header_id integer NOT NULL, header_id integer NOT NULL,
tx_idx integer,
ilk bytea, ilk bytea,
lad bytea, urn bytea,
dink numeric, dink numeric,
dart numeric, dart numeric,
ink numeric, ink numeric,
art numeric, art numeric,
iart numeric iart numeric,
tx_idx integer NOT NULL,
raw_log jsonb
); );
@ -155,6 +156,109 @@ CREATE SEQUENCE maker.frob_id_seq
ALTER SEQUENCE maker.frob_id_seq OWNED BY maker.frob.id; ALTER SEQUENCE maker.frob_id_seq OWNED BY maker.frob.id;
--
-- Name: pit_file_debt_ceiling; Type: TABLE; Schema: maker; Owner: -
--
CREATE TABLE maker.pit_file_debt_ceiling (
id integer NOT NULL,
header_id integer NOT NULL,
what text,
data numeric,
tx_idx integer NOT NULL,
raw_log jsonb
);
--
-- Name: pit_file_debt_ceiling_id_seq; Type: SEQUENCE; Schema: maker; Owner: -
--
CREATE SEQUENCE maker.pit_file_debt_ceiling_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: pit_file_debt_ceiling_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: -
--
ALTER SEQUENCE maker.pit_file_debt_ceiling_id_seq OWNED BY maker.pit_file_debt_ceiling.id;
--
-- Name: pit_file_ilk; Type: TABLE; Schema: maker; Owner: -
--
CREATE TABLE maker.pit_file_ilk (
id integer NOT NULL,
header_id integer NOT NULL,
ilk text,
what text,
data numeric,
tx_idx integer NOT NULL,
raw_log jsonb
);
--
-- Name: pit_file_ilk_id_seq; Type: SEQUENCE; Schema: maker; Owner: -
--
CREATE SEQUENCE maker.pit_file_ilk_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: pit_file_ilk_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: -
--
ALTER SEQUENCE maker.pit_file_ilk_id_seq OWNED BY maker.pit_file_ilk.id;
--
-- Name: pit_file_stability_fee; Type: TABLE; Schema: maker; Owner: -
--
CREATE TABLE maker.pit_file_stability_fee (
id integer NOT NULL,
header_id integer NOT NULL,
what text,
data text,
tx_idx integer NOT NULL,
raw_log jsonb
);
--
-- Name: pit_file_stability_fee_id_seq; Type: SEQUENCE; Schema: maker; Owner: -
--
CREATE SEQUENCE maker.pit_file_stability_fee_id_seq
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: pit_file_stability_fee_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: -
--
ALTER SEQUENCE maker.pit_file_stability_fee_id_seq OWNED BY maker.pit_file_stability_fee.id;
-- --
-- Name: price_feeds; Type: TABLE; Schema: maker; Owner: - -- Name: price_feeds; Type: TABLE; Schema: maker; Owner: -
-- --
@ -619,6 +723,27 @@ ALTER TABLE ONLY maker.flip_kick ALTER COLUMN db_id SET DEFAULT nextval('maker.f
ALTER TABLE ONLY maker.frob ALTER COLUMN id SET DEFAULT nextval('maker.frob_id_seq'::regclass); ALTER TABLE ONLY maker.frob ALTER COLUMN id SET DEFAULT nextval('maker.frob_id_seq'::regclass);
--
-- Name: pit_file_debt_ceiling id; Type: DEFAULT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_debt_ceiling ALTER COLUMN id SET DEFAULT nextval('maker.pit_file_debt_ceiling_id_seq'::regclass);
--
-- Name: pit_file_ilk id; Type: DEFAULT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_ilk ALTER COLUMN id SET DEFAULT nextval('maker.pit_file_ilk_id_seq'::regclass);
--
-- Name: pit_file_stability_fee id; Type: DEFAULT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_stability_fee ALTER COLUMN id SET DEFAULT nextval('maker.pit_file_stability_fee_id_seq'::regclass);
-- --
-- Name: price_feeds id; Type: DEFAULT; Schema: maker; Owner: - -- Name: price_feeds id; Type: DEFAULT; Schema: maker; Owner: -
-- --
@ -744,6 +869,54 @@ ALTER TABLE ONLY maker.frob
ADD CONSTRAINT frob_pkey PRIMARY KEY (id); ADD CONSTRAINT frob_pkey PRIMARY KEY (id);
--
-- Name: pit_file_debt_ceiling pit_file_debt_ceiling_header_id_tx_idx_key; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_debt_ceiling
ADD CONSTRAINT pit_file_debt_ceiling_header_id_tx_idx_key UNIQUE (header_id, tx_idx);
--
-- Name: pit_file_debt_ceiling pit_file_debt_ceiling_pkey; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_debt_ceiling
ADD CONSTRAINT pit_file_debt_ceiling_pkey PRIMARY KEY (id);
--
-- Name: pit_file_ilk pit_file_ilk_header_id_tx_idx_key; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_ilk
ADD CONSTRAINT pit_file_ilk_header_id_tx_idx_key UNIQUE (header_id, tx_idx);
--
-- Name: pit_file_ilk pit_file_ilk_pkey; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_ilk
ADD CONSTRAINT pit_file_ilk_pkey PRIMARY KEY (id);
--
-- Name: pit_file_stability_fee pit_file_stability_fee_header_id_tx_idx_key; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_stability_fee
ADD CONSTRAINT pit_file_stability_fee_header_id_tx_idx_key UNIQUE (header_id, tx_idx);
--
-- Name: pit_file_stability_fee pit_file_stability_fee_pkey; Type: CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_stability_fee
ADD CONSTRAINT pit_file_stability_fee_pkey PRIMARY KEY (id);
-- --
-- Name: price_feeds price_feeds_header_id_medianizer_address_tx_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - -- Name: price_feeds price_feeds_header_id_medianizer_address_tx_idx_key; Type: CONSTRAINT; Schema: maker; Owner: -
-- --
@ -939,6 +1112,30 @@ ALTER TABLE ONLY maker.price_feeds
ADD CONSTRAINT headers_fk FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE; ADD CONSTRAINT headers_fk FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE;
--
-- Name: pit_file_debt_ceiling pit_file_debt_ceiling_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_debt_ceiling
ADD CONSTRAINT pit_file_debt_ceiling_header_id_fkey FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE;
--
-- Name: pit_file_ilk pit_file_ilk_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_ilk
ADD CONSTRAINT pit_file_ilk_header_id_fkey FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE;
--
-- Name: pit_file_stability_fee pit_file_stability_fee_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: -
--
ALTER TABLE ONLY maker.pit_file_stability_fee
ADD CONSTRAINT pit_file_stability_fee_header_id_fkey FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE;
-- --
-- Name: tend tend_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: - -- Name: tend tend_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: -
-- --

View File

@ -19,9 +19,15 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"io/ioutil"
"log"
) )
func TestBite(t *testing.T) { func TestBite(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Bite Suite") RunSpecs(t, "Bite Suite")
} }
var _ = BeforeSuite(func() {
log.SetOutput(ioutil.Discard)
})

View File

@ -21,9 +21,9 @@ import (
) )
var BiteConfig = shared.TransformerConfig{ var BiteConfig = shared.TransformerConfig{
ContractAddresses: "0xe0f0fa6982c59d8aa4ae0134bfe048327bd788cacf758b643ca41f055ffce76c", //this is a temporary address deployed locally ContractAddress: "0xe0f0fa6982c59d8aa4ae0134bfe048327bd788cacf758b643ca41f055ffce76c", //this is a temporary address deployed locally
ContractAbi: BiteABI, ContractAbi: shared.CatABI,
Topics: []string{BiteSignature}, Topics: []string{shared.BiteSignature},
StartingBlockNumber: 0, StartingBlockNumber: 0,
EndingBlockNumber: 100, EndingBlockNumber: 100,
} }

View File

@ -1,22 +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 bite
var (
BiteABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"vat\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vow\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"flips\",\"outputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"lad\",\"type\":\"bytes32\"},{\"name\":\"ink\",\"type\":\"uint256\"},{\"name\":\"tab\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nflip\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"live\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"wards\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"ilks\",\"outputs\":[{\"name\":\"flip\",\"type\":\"address\"},{\"name\":\"chop\",\"type\":\"uint256\"},{\"name\":\"lump\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pit\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"vat_\",\"type\":\"address\"},{\"name\":\"pit_\",\"type\":\"address\"},{\"name\":\"vow_\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"ilk\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"lad\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ink\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"art\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"tab\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"flip\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"iArt\",\"type\":\"uint256\"}],\"name\":\"Bite\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":true,\"name\":\"sig\",\"type\":\"bytes4\"},{\"indexed\":true,\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"foo\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"bar\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"wad\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"fax\",\"type\":\"bytes\"}],\"name\":\"LogNote\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"name\":\"guy\",\"type\":\"address\"}],\"name\":\"rely\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"guy\",\"type\":\"address\"}],\"name\":\"deny\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"what\",\"type\":\"bytes32\"},{\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"file\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"what\",\"type\":\"bytes32\"},{\"name\":\"flip\",\"type\":\"address\"}],\"name\":\"file\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"lad\",\"type\":\"bytes32\"}],\"name\":\"bite\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"n\",\"type\":\"uint256\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"flip\",\"outputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
BiteSignature = "0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"
)

View File

@ -26,6 +26,7 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
) )
var _ = Describe("Bite Converter", func() { var _ = Describe("Bite Converter", func() {
@ -33,7 +34,7 @@ var _ = Describe("Bite Converter", func() {
Describe("ToEntity", func() { Describe("ToEntity", func() {
It("converts an eth log to a bite entity", func() { It("converts an eth log to a bite entity", func() {
entity, err := converter.ToEntity(test_data.TemporaryBiteAddress, bite.BiteABI, test_data.EthBiteLog) entity, err := converter.ToEntity(test_data.TemporaryBiteAddress, shared.CatABI, test_data.EthBiteLog)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(entity.Ilk).To(Equal(test_data.BiteEntity.Ilk)) Expect(entity.Ilk).To(Equal(test_data.BiteEntity.Ilk))

View File

@ -48,7 +48,7 @@ var _ = Describe("Integration tests", func() {
transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) transactionConverter := rpc2.NewRpcTransactionConverter(ethClient)
realBlockChain := geth.NewBlockChain(blockChainClient, realNode, transactionConverter) realBlockChain := geth.NewBlockChain(blockChainClient, realNode, transactionConverter)
realFetcher := shared.NewFetcher(realBlockChain) realFetcher := shared.NewFetcher(realBlockChain)
topic0 := common.HexToHash(bite.BiteSignature) topic0 := common.HexToHash(shared.BiteSignature)
topics := [][]common.Hash{{topic0}} topics := [][]common.Hash{{topic0}}
result, err := realFetcher.FetchLogs(test_data.TemporaryBiteAddress, topics, int64(26)) result, err := realFetcher.FetchLogs(test_data.TemporaryBiteAddress, topics, int64(26))
@ -64,7 +64,7 @@ var _ = Describe("Integration tests", func() {
It("unpacks an event log", func() { It("unpacks an event log", func() {
address := common.HexToAddress(test_data.TemporaryBiteAddress) address := common.HexToAddress(test_data.TemporaryBiteAddress)
abi, err := geth.ParseAbi(bite.BiteABI) abi, err := geth.ParseAbi(shared.CatABI)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
contract := bind.NewBoundContract(address, abi, nil, nil, nil) contract := bind.NewBoundContract(address, abi, nil, nil, nil)

View File

@ -59,14 +59,14 @@ func (b BiteTransformer) Execute() error {
} }
for _, header := range missingHeaders { for _, header := range missingHeaders {
ethLogs, err := b.Fetcher.FetchLogs(config.ContractAddresses, topics, header.BlockNumber) ethLogs, err := b.Fetcher.FetchLogs(config.ContractAddress, topics, header.BlockNumber)
if err != nil { if err != nil {
log.Println("Error fetching matching logs:", err) log.Println("Error fetching matching logs:", err)
return err return err
} }
for _, ethLog := range ethLogs { for _, ethLog := range ethLogs {
entity, err := b.Converter.ToEntity(config.ContractAddresses, config.ContractAbi, ethLog) entity, err := b.Converter.ToEntity(config.ContractAddress, config.ContractAbi, ethLog)
model, err := b.Converter.ToModel(entity) model, err := b.Converter.ToModel(entity)
if err != nil { if err != nil {
log.Println("Error converting logs:", err) log.Println("Error converting logs:", err)

View File

@ -53,7 +53,7 @@ var _ = Describe("Bite Transformer", func() {
} }
testConfig = shared.TransformerConfig{ testConfig = shared.TransformerConfig{
ContractAddresses: "0x12345", ContractAddress: "0x12345",
ContractAbi: "test abi", ContractAbi: "test abi",
Topics: []string{shared.BiteSignature}, Topics: []string{shared.BiteSignature},
StartingBlockNumber: blockNumber1, StartingBlockNumber: blockNumber1,
@ -85,7 +85,7 @@ var _ = Describe("Bite Transformer", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(fetcher.FetchedBlocks).To(Equal([]int64{blockNumber1, blockNumber2})) Expect(fetcher.FetchedBlocks).To(Equal([]int64{blockNumber1, blockNumber2}))
Expect(fetcher.FetchedTopics).To(Equal(expectedTopics)) Expect(fetcher.FetchedTopics).To(Equal(expectedTopics))
Expect(fetcher.FetchedContractAddress).To(Equal(bite.BiteConfig.ContractAddresses)) Expect(fetcher.FetchedContractAddress).To(Equal(bite.BiteConfig.ContractAddress))
}) })
It("returns an error if fetching logs fails", func() { It("returns an error if fetching logs fails", func() {
@ -103,7 +103,7 @@ var _ = Describe("Bite Transformer", func() {
err := transformer.Execute() err := transformer.Execute()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(converter.ConverterContract).To(Equal(bite.BiteConfig.ContractAddresses)) Expect(converter.ConverterContract).To(Equal(bite.BiteConfig.ContractAddress))
Expect(converter.ConverterAbi).To(Equal(bite.BiteConfig.ContractAbi)) Expect(converter.ConverterAbi).To(Equal(bite.BiteConfig.ContractAbi))
Expect(converter.LogsToConvert).To(Equal([]types.Log{test_data.EthBiteLog})) Expect(converter.LogsToConvert).To(Equal([]types.Log{test_data.EthBiteLog}))
}) })

View File

@ -17,7 +17,7 @@ package flip_kick
import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
var FlipKickConfig = shared.TransformerConfig{ var FlipKickConfig = shared.TransformerConfig{
ContractAddresses: shared.FlipperContractAddress, ContractAddress: shared.FlipperContractAddress,
ContractAbi: shared.FlipperABI, ContractAbi: shared.FlipperABI,
Topics: []string{shared.FlipKickSignature}, Topics: []string{shared.FlipKickSignature},
StartingBlockNumber: 0, StartingBlockNumber: 0,

View File

@ -91,13 +91,13 @@ func (fkt FlipKickTransformer) Execute() error {
log.Printf("Fetching event logs for %d headers \n", len(headers)) log.Printf("Fetching event logs for %d headers \n", len(headers))
var resultingErrors []error var resultingErrors []error
for _, header := range headers { for _, header := range headers {
ethLogs, err := fkt.Fetcher.FetchLogs(config.ContractAddresses, topics, header.BlockNumber) ethLogs, err := fkt.Fetcher.FetchLogs(config.ContractAddress, topics, header.BlockNumber)
if err != nil { if err != nil {
resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, FetcherError)) resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, FetcherError))
} }
for _, ethLog := range ethLogs { for _, ethLog := range ethLogs {
entity, err := fkt.Converter.ToEntity(config.ContractAddresses, config.ContractAbi, ethLog) entity, err := fkt.Converter.ToEntity(config.ContractAddress, config.ContractAbi, ethLog)
if err != nil { if err != nil {
resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, LogToEntityError)) resultingErrors = append(resultingErrors, newTransformerError(err, header.BlockNumber, LogToEntityError))
} }

View File

@ -54,7 +54,7 @@ var _ = Describe("FlipKick Transformer", func() {
startingBlockNumber := rand.Int63() startingBlockNumber := rand.Int63()
testConfig = shared.TransformerConfig{ testConfig = shared.TransformerConfig{
ContractAddresses: "0x12345", ContractAddress: "0x12345",
ContractAbi: "test abi", ContractAbi: "test abi",
Topics: []string{shared.FlipKickSignature}, Topics: []string{shared.FlipKickSignature},
StartingBlockNumber: startingBlockNumber, StartingBlockNumber: startingBlockNumber,
@ -83,7 +83,7 @@ var _ = Describe("FlipKick Transformer", func() {
err := transformer.Execute() err := transformer.Execute()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(fetcher.FetchedContractAddress).To(Equal(testConfig.ContractAddresses)) Expect(fetcher.FetchedContractAddress).To(Equal(testConfig.ContractAddress))
Expect(fetcher.FetchedTopics).To(Equal(expectedTopics)) Expect(fetcher.FetchedTopics).To(Equal(expectedTopics))
Expect(fetcher.FetchedBlocks).To(Equal([]int64{blockNumber})) Expect(fetcher.FetchedBlocks).To(Equal([]int64{blockNumber}))
}) })
@ -100,7 +100,7 @@ var _ = Describe("FlipKick Transformer", func() {
err := transformer.Execute() err := transformer.Execute()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(converter.ConverterContract).To(Equal(testConfig.ContractAddresses)) Expect(converter.ConverterContract).To(Equal(testConfig.ContractAddress))
Expect(converter.ConverterAbi).To(Equal(testConfig.ContractAbi)) Expect(converter.ConverterAbi).To(Equal(testConfig.ContractAbi))
Expect(converter.LogsToConvert).To(Equal(logs)) Expect(converter.LogsToConvert).To(Equal(logs))
Expect(converter.EntitiesToConvert).To(Equal([]flip_kick.FlipKickEntity{test_data.FlipKickEntity})) Expect(converter.EntitiesToConvert).To(Equal([]flip_kick.FlipKickEntity{test_data.FlipKickEntity}))

View File

@ -17,9 +17,9 @@ package frob
import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
var FrobConfig = shared.TransformerConfig{ var FrobConfig = shared.TransformerConfig{
ContractAddresses: "0xff3f2400f1600f3f493a9a92704a29b96795af1a", //this is a temporary address deployed locally ContractAddress: "0xff3f2400f1600f3f493a9a92704a29b96795af1a", //this is a temporary address deployed locally
ContractAbi: FrobABI, ContractAbi: shared.PitABI,
Topics: []string{FrobEventSignature}, Topics: []string{shared.FrobSignature},
StartingBlockNumber: 0, StartingBlockNumber: 0,
EndingBlockNumber: 100, EndingBlockNumber: 100,
} }

View File

@ -1,20 +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 frob
var (
FrobABI = `[{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"live","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"drip","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"Line","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"ilks","outputs":[{"name":"spot","type":"uint256"},{"name":"line","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"vat_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"ilk","type":"bytes32"},{"indexed":true,"name":"lad","type":"bytes32"},{"indexed":false,"name":"ink","type":"uint256"},{"indexed":false,"name":"art","type":"uint256"},{"indexed":false,"name":"dink","type":"int256"},{"indexed":false,"name":"dart","type":"int256"},{"indexed":false,"name":"iArt","type":"uint256"}],"name":"Frob","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"dink","type":"int256"},{"name":"dart","type":"int256"}],"name":"frob","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
FrobEventSignature = "0x6cedf1d3a466a3d6bab04887b1642177bf6dbf1daa737c2e8f639cd0b020d9d0"
)

View File

@ -19,12 +19,13 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"encoding/json"
"github.com/vulcanize/vulcanizedb/pkg/geth" "github.com/vulcanize/vulcanizedb/pkg/geth"
) )
type Converter interface { type Converter interface {
ToEntity(contractAddress string, contractAbi string, ethLog types.Log) (FrobEntity, error) ToEntity(contractAddress string, contractAbi string, ethLog types.Log) (FrobEntity, error)
ToModel(flipKick FrobEntity) FrobModel ToModel(flipKick FrobEntity) (FrobModel, error)
} }
type FrobConverter struct { type FrobConverter struct {
@ -39,17 +40,25 @@ func (FrobConverter) ToEntity(contractAddress string, contractAbi string, ethLog
} }
contract := bind.NewBoundContract(address, abi, nil, nil, nil) contract := bind.NewBoundContract(address, abi, nil, nil, nil)
err = contract.UnpackLog(&entity, "Frob", ethLog) err = contract.UnpackLog(&entity, "Frob", ethLog)
entity.TransactionIndex = ethLog.TxIndex
entity.Raw = ethLog
return entity, err return entity, err
} }
func (FrobConverter) ToModel(frob FrobEntity) FrobModel { func (FrobConverter) ToModel(frob FrobEntity) (FrobModel, error) {
return FrobModel{ rawLog, err := json.Marshal(frob.Raw)
Ilk: frob.Ilk[:], if err != nil {
Lad: frob.Lad[:], return FrobModel{}, err
Dink: frob.Dink.String(),
Dart: frob.Dart.String(),
Ink: frob.Ink.String(),
Art: frob.Art.String(),
IArt: frob.IArt.String(),
} }
return FrobModel{
Ilk: frob.Ilk[:],
Urn: frob.Urn[:],
Ink: frob.Ink.String(),
Art: frob.Art.String(),
Dink: frob.Dink.String(),
Dart: frob.Dart.String(),
IArt: frob.IArt.String(),
TransactionIndex: frob.TransactionIndex,
Raw: rawLog,
}, nil
} }

View File

@ -19,6 +19,7 @@ import (
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/transformers/frob" "github.com/vulcanize/vulcanizedb/pkg/transformers/frob"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
) )
@ -26,7 +27,7 @@ var _ = Describe("Frob converter", func() {
It("converts a log to an entity", func() { It("converts a log to an entity", func() {
converter := frob.FrobConverter{} converter := frob.FrobConverter{}
entity, err := converter.ToEntity(test_data.TemporaryFrobAddress, frob.FrobABI, test_data.EthFrobLog) entity, err := converter.ToEntity(test_data.TemporaryFrobAddress, shared.PitABI, test_data.EthFrobLog)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(entity).To(Equal(test_data.FrobEntity)) Expect(entity).To(Equal(test_data.FrobEntity))
@ -35,8 +36,9 @@ var _ = Describe("Frob converter", func() {
It("converts an entity to a model", func() { It("converts an entity to a model", func() {
converter := frob.FrobConverter{} converter := frob.FrobConverter{}
model := converter.ToModel(test_data.FrobEntity) model, err := converter.ToModel(test_data.FrobEntity)
Expect(err).NotTo(HaveOccurred())
Expect(model).To(Equal(test_data.FrobModel)) Expect(model).To(Equal(test_data.FrobModel))
}) })
}) })

View File

@ -16,14 +16,18 @@ package frob
import ( import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/core/types"
) )
type FrobEntity struct { type FrobEntity struct {
Ilk [32]byte Ilk [32]byte
Lad [32]byte Urn [32]byte
Ink *big.Int Ink *big.Int
Art *big.Int Art *big.Int
Dink *big.Int Dink *big.Int
Dart *big.Int Dart *big.Int
IArt *big.Int IArt *big.Int
TransactionIndex uint
Raw types.Log
} }

View File

@ -46,7 +46,7 @@ var _ = Describe("Integration tests", func() {
transactionConverter := vRpc.NewRpcTransactionConverter(ethClient) transactionConverter := vRpc.NewRpcTransactionConverter(ethClient)
realBlockChain := geth.NewBlockChain(blockChainClient, realNode, transactionConverter) realBlockChain := geth.NewBlockChain(blockChainClient, realNode, transactionConverter)
realFetcher := shared.NewFetcher(realBlockChain) realFetcher := shared.NewFetcher(realBlockChain)
topic0 := common.HexToHash(frob.FrobEventSignature) topic0 := common.HexToHash(shared.FrobSignature)
topics := [][]common.Hash{{topic0}} topics := [][]common.Hash{{topic0}}
result, err := realFetcher.FetchLogs(test_data.TemporaryFrobAddress, topics, int64(12)) result, err := realFetcher.FetchLogs(test_data.TemporaryFrobAddress, topics, int64(12))
@ -62,7 +62,7 @@ var _ = Describe("Integration tests", func() {
It("unpacks an event log", func() { It("unpacks an event log", func() {
address := common.HexToAddress(test_data.TemporaryFrobAddress) address := common.HexToAddress(test_data.TemporaryFrobAddress)
abi, err := geth.ParseAbi(frob.FrobABI) abi, err := geth.ParseAbi(shared.PitABI)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
contract := bind.NewBoundContract(address, abi, nil, nil, nil) contract := bind.NewBoundContract(address, abi, nil, nil, nil)
@ -78,6 +78,6 @@ var _ = Describe("Integration tests", func() {
Expect(entity.IArt).To(Equal(expectedEntity.IArt)) Expect(entity.IArt).To(Equal(expectedEntity.IArt))
Expect(entity.Ilk).To(Equal(expectedEntity.Ilk)) Expect(entity.Ilk).To(Equal(expectedEntity.Ilk))
Expect(entity.Ink).To(Equal(expectedEntity.Ink)) Expect(entity.Ink).To(Equal(expectedEntity.Ink))
Expect(entity.Lad).To(Equal(expectedEntity.Lad)) Expect(entity.Urn).To(Equal(expectedEntity.Urn))
}) })
}) })

View File

@ -15,11 +15,13 @@
package frob package frob
type FrobModel struct { type FrobModel struct {
Ilk []byte Ilk []byte
Lad []byte Urn []byte
Ink string Ink string
Art string Art string
Dink string Dink string
Dart string Dart string
IArt string IArt string
TransactionIndex uint `db:"tx_idx"`
Raw []byte `db:"raw_log"`
} }

View File

@ -20,7 +20,7 @@ import (
) )
type Repository interface { type Repository interface {
Create(headerID int64, transactionIndex uint, model FrobModel) error Create(headerID int64, model FrobModel) error
MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error)
} }
@ -32,10 +32,10 @@ func NewFrobRepository(db *postgres.DB) FrobRepository {
return FrobRepository{db: db} return FrobRepository{db: db}
} }
func (repository FrobRepository) Create(headerID int64, transactionIndex uint, model FrobModel) error { func (repository FrobRepository) Create(headerID int64, model FrobModel) error {
_, err := repository.db.Exec(`INSERT INTO maker.frob (header_id, tx_idx, art, dart, dink, iart, ilk, ink, lad) _, err := repository.db.Exec(`INSERT INTO maker.frob (header_id, art, dart, dink, iart, ilk, ink, urn, raw_log, tx_idx)
VALUES($1, $2, $3::NUMERIC, $4::NUMERIC, $5::NUMERIC, $6::NUMERIC, $7, $8::NUMERIC, $9)`, VALUES($1, $2::NUMERIC, $3::NUMERIC, $4::NUMERIC, $5::NUMERIC, $6, $7::NUMERIC, $8, $9, $10)`,
headerID, transactionIndex, model.Art, model.Dart, model.Dink, model.IArt, model.Ilk, model.Ink, model.Lad) headerID, model.Art, model.Dart, model.Dink, model.IArt, model.Ilk, model.Ink, model.Urn, model.Raw, model.TransactionIndex)
return err return err
} }

View File

@ -30,56 +30,61 @@ import (
var _ = Describe("Frob repository", func() { var _ = Describe("Frob repository", func() {
Describe("Create", func() { Describe("Create", func() {
It("adds a frob", func() { It("adds a frob", func() {
node := core.Node{} db := test_config.NewTestDB(core.Node{})
db := test_config.NewTestDB(node)
test_config.CleanTestDB(db) test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db) headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{}) headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
frobRepository := frob.NewFrobRepository(db) frobRepository := frob.NewFrobRepository(db)
err = frobRepository.Create(headerID, 123, test_data.FrobModel) err = frobRepository.Create(headerID, test_data.FrobModel)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
var dbFrob frob.FrobModel var dbFrob frob.FrobModel
err = db.Get(&dbFrob, `SELECT art, dart, dink, iart, ilk, ink, lad FROM maker.frob WHERE header_id = $1`, headerID) err = db.Get(&dbFrob, `SELECT art, dart, dink, iart, ilk, ink, urn, tx_idx, raw_log FROM maker.frob WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(dbFrob).To(Equal(test_data.FrobModel)) Expect(dbFrob.Ilk).To(Equal(test_data.FrobModel.Ilk))
Expect(dbFrob.Urn).To(Equal(test_data.FrobModel.Urn))
Expect(dbFrob.Ink).To(Equal(test_data.FrobModel.Ink))
Expect(dbFrob.Art).To(Equal(test_data.FrobModel.Art))
Expect(dbFrob.Dink).To(Equal(test_data.FrobModel.Dink))
Expect(dbFrob.Dart).To(Equal(test_data.FrobModel.Dart))
Expect(dbFrob.IArt).To(Equal(test_data.FrobModel.IArt))
Expect(dbFrob.TransactionIndex).To(Equal(test_data.FrobModel.TransactionIndex))
Expect(dbFrob.Raw).To(MatchJSON(test_data.FrobModel.Raw))
}) })
It("does not duplicate frob events", func() { It("does not duplicate frob events", func() {
node := core.Node{} db := test_config.NewTestDB(core.Node{})
db := test_config.NewTestDB(node)
test_config.CleanTestDB(db) test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db) headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{}) headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
frobRepository := frob.NewFrobRepository(db) frobRepository := frob.NewFrobRepository(db)
err = frobRepository.Create(headerID, 123, test_data.FrobModel) err = frobRepository.Create(headerID, test_data.FrobModel)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
err = frobRepository.Create(headerID, 123, test_data.FrobModel) err = frobRepository.Create(headerID, test_data.FrobModel)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint")) Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint"))
}) })
It("removes frob if corresponding header is deleted", func() { It("removes frob if corresponding header is deleted", func() {
node := core.Node{} db := test_config.NewTestDB(core.Node{})
db := test_config.NewTestDB(node)
test_config.CleanTestDB(db) test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db) headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{}) headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
frobRepository := frob.NewFrobRepository(db) frobRepository := frob.NewFrobRepository(db)
err = frobRepository.Create(headerID, 123, test_data.FrobModel) err = frobRepository.Create(headerID, test_data.FrobModel)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
_, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID) _, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
var dbFrob frob.FrobModel var dbFrob frob.FrobModel
err = db.Get(&dbFrob, `SELECT art, iart, ilk, ink, lad FROM maker.frob WHERE header_id = $1`, headerID) err = db.Get(&dbFrob, `SELECT art, iart, ilk, ink, urn, tx_idx, raw_log FROM maker.frob WHERE header_id = $1`, headerID)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(sql.ErrNoRows)) Expect(err).To(MatchError(sql.ErrNoRows))
}) })
@ -87,8 +92,7 @@ var _ = Describe("Frob repository", func() {
Describe("MissingHeaders", func() { Describe("MissingHeaders", func() {
It("returns headers with no associated frob event", func() { It("returns headers with no associated frob event", func() {
node := core.Node{} db := test_config.NewTestDB(core.Node{})
db := test_config.NewTestDB(node)
test_config.CleanTestDB(db) test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db) headerRepository := repositories.NewHeaderRepository(db)
startingBlockNumber := int64(1) startingBlockNumber := int64(1)
@ -102,7 +106,7 @@ var _ = Describe("Frob repository", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
} }
frobRepository := frob.NewFrobRepository(db) frobRepository := frob.NewFrobRepository(db)
err := frobRepository.Create(headerIDs[1], 123, test_data.FrobModel) err := frobRepository.Create(headerIDs[1], test_data.FrobModel)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
headers, err := frobRepository.MissingHeaders(startingBlockNumber, endingBlockNumber) headers, err := frobRepository.MissingHeaders(startingBlockNumber, endingBlockNumber)
@ -114,13 +118,11 @@ var _ = Describe("Frob repository", func() {
}) })
It("only returns headers associated with the current node", func() { It("only returns headers associated with the current node", func() {
nodeOne := core.Node{} db := test_config.NewTestDB(core.Node{})
db := test_config.NewTestDB(nodeOne)
test_config.CleanTestDB(db) test_config.CleanTestDB(db)
blockNumbers := []int64{1, 2, 3} blockNumbers := []int64{1, 2, 3}
headerRepository := repositories.NewHeaderRepository(db) headerRepository := repositories.NewHeaderRepository(db)
nodeTwo := core.Node{ID: "second"} dbTwo := test_config.NewTestDB(core.Node{ID: "second"})
dbTwo := test_config.NewTestDB(nodeTwo)
headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo) headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo)
var headerIDs []int64 var headerIDs []int64
for _, n := range blockNumbers { for _, n := range blockNumbers {
@ -132,7 +134,7 @@ var _ = Describe("Frob repository", func() {
} }
frobRepository := frob.NewFrobRepository(db) frobRepository := frob.NewFrobRepository(db)
frobRepositoryTwo := frob.NewFrobRepository(dbTwo) frobRepositoryTwo := frob.NewFrobRepository(dbTwo)
err := frobRepository.Create(headerIDs[0], 0, test_data.FrobModel) err := frobRepository.Create(headerIDs[0], test_data.FrobModel)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
nodeOneMissingHeaders, err := frobRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1]) nodeOneMissingHeaders, err := frobRepository.MissingHeaders(blockNumbers[0], blockNumbers[len(blockNumbers)-1])

View File

@ -51,18 +51,21 @@ func (transformer FrobTransformer) Execute() error {
return err return err
} }
for _, header := range missingHeaders { for _, header := range missingHeaders {
topics := [][]common.Hash{{common.HexToHash(FrobEventSignature)}} topics := [][]common.Hash{{common.HexToHash(shared.FrobSignature)}}
matchingLogs, err := transformer.Fetcher.FetchLogs(FrobConfig.ContractAddresses, topics, header.BlockNumber) matchingLogs, err := transformer.Fetcher.FetchLogs(FrobConfig.ContractAddress, topics, header.BlockNumber)
if err != nil { if err != nil {
return err return err
} }
for _, log := range matchingLogs { for _, log := range matchingLogs {
entity, err := transformer.Converter.ToEntity(FrobConfig.ContractAddresses, FrobConfig.ContractAbi, log) entity, err := transformer.Converter.ToEntity(FrobConfig.ContractAddress, FrobConfig.ContractAbi, log)
if err != nil { if err != nil {
return err return err
} }
model := transformer.Converter.ToModel(entity) model, err := transformer.Converter.ToModel(entity)
err = transformer.Repository.Create(header.Id, log.TxIndex, model) if err != nil {
return err
}
err = transformer.Repository.Create(header.Id, model)
if err != nil { if err != nil {
return err return err
} }

View File

@ -23,6 +23,7 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/fakes" "github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/transformers/frob" "github.com/vulcanize/vulcanizedb/pkg/transformers/frob"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks" "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks"
frob_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/frob" frob_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/frob"
@ -74,8 +75,8 @@ var _ = Describe("Frob transformer", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2})) Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2}))
Expect(fetcher.FetchedContractAddress).To(Equal(frob.FrobConfig.ContractAddresses)) Expect(fetcher.FetchedContractAddress).To(Equal(frob.FrobConfig.ContractAddress))
Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(frob.FrobEventSignature)}})) Expect(fetcher.FetchedTopics).To(Equal([][]common.Hash{{common.HexToHash(shared.FrobSignature)}}))
}) })
It("returns error if fetcher returns error", func() { It("returns error if fetcher returns error", func() {
@ -95,7 +96,7 @@ var _ = Describe("Frob transformer", func() {
Expect(err).To(MatchError(fakes.FakeError)) Expect(err).To(MatchError(fakes.FakeError))
}) })
It("converts matching logs", func() { It("converts matching logs to entity", func() {
converter := &frob_mocks.MockFrobConverter{} converter := &frob_mocks.MockFrobConverter{}
fetcher := &mocks.MockLogFetcher{} fetcher := &mocks.MockLogFetcher{}
fetcher.SetFetchedLogs([]types.Log{test_data.EthFrobLog}) fetcher.SetFetchedLogs([]types.Log{test_data.EthFrobLog})
@ -110,15 +111,51 @@ var _ = Describe("Frob transformer", func() {
err := transformer.Execute() err := transformer.Execute()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(converter.PassedContractAddress).To(Equal(frob.FrobConfig.ContractAddresses)) Expect(converter.PassedContractAddress).To(Equal(frob.FrobConfig.ContractAddress))
Expect(converter.PassedContractABI).To(Equal(frob.FrobConfig.ContractAbi)) Expect(converter.PassedContractABI).To(Equal(frob.FrobConfig.ContractAbi))
Expect(converter.PassedLog).To(Equal(test_data.EthFrobLog)) Expect(converter.PassedLog).To(Equal(test_data.EthFrobLog))
})
It("returns error if converting to entity returns error", func() {
converter := &frob_mocks.MockFrobConverter{}
converter.SetToEntityError(fakes.FakeError)
fetcher := &mocks.MockLogFetcher{}
fetcher.SetFetchedLogs([]types.Log{test_data.EthFrobLog})
repository := &frob_mocks.MockFrobRepository{}
repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}})
transformer := frob.FrobTransformer{
Fetcher: fetcher,
Converter: converter,
Repository: repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
It("converts frob entity to model", func() {
converter := &frob_mocks.MockFrobConverter{}
fetcher := &mocks.MockLogFetcher{}
fetcher.SetFetchedLogs([]types.Log{test_data.EthFrobLog})
repository := &frob_mocks.MockFrobRepository{}
repository.SetMissingHeaders([]core.Header{{BlockNumber: 1}})
transformer := frob.FrobTransformer{
Fetcher: fetcher,
Converter: converter,
Repository: repository,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(converter.PassedEntity).To(Equal(test_data.FrobEntity)) Expect(converter.PassedEntity).To(Equal(test_data.FrobEntity))
}) })
It("returns error if converter returns error", func() { It("returns error if converting to model returns error", func() {
converter := &frob_mocks.MockFrobConverter{} converter := &frob_mocks.MockFrobConverter{}
converter.SetConverterError(fakes.FakeError) converter.SetToModelError(fakes.FakeError)
fetcher := &mocks.MockLogFetcher{} fetcher := &mocks.MockLogFetcher{}
fetcher.SetFetchedLogs([]types.Log{test_data.EthFrobLog}) fetcher.SetFetchedLogs([]types.Log{test_data.EthFrobLog})
repository := &frob_mocks.MockFrobRepository{} repository := &frob_mocks.MockFrobRepository{}
@ -152,7 +189,6 @@ var _ = Describe("Frob transformer", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id)) Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id))
Expect(repository.PassedTransactionIndex).To(Equal(test_data.EthFrobLog.TxIndex))
Expect(repository.PassedFrobModel).To(Equal(test_data.FrobModel)) Expect(repository.PassedFrobModel).To(Equal(test_data.FrobModel))
}) })

View File

@ -0,0 +1,13 @@
package pit_file
import (
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
)
var PitFileConfig = shared.TransformerConfig{
ContractAddress: "0xff3f2400f1600f3f493a9a92704a29b96795af1a", // temporary address from Ganache deploy
ContractAbi: shared.PitABI,
Topics: []string{shared.PitFileIlkSignature, shared.PitFileDebtCeilingSignature, shared.PitFileStabilityFeeSignature},
StartingBlockNumber: 0,
EndingBlockNumber: 100,
}

View File

@ -0,0 +1,29 @@
package debt_ceiling
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"math/big"
)
type Converter interface {
ToModel(contractAddress string, contractAbi string, ethLog types.Log) (PitFileDebtCeilingModel, error)
}
type PitFileDebtCeilingConverter struct{}
func (PitFileDebtCeilingConverter) ToModel(contractAddress string, contractAbi string, ethLog types.Log) (PitFileDebtCeilingModel, error) {
what := common.HexToAddress(ethLog.Topics[1].String()).String()
itemByteLength := 32
riskBytes := ethLog.Data[len(ethLog.Data)-itemByteLength:]
data := big.NewInt(0).SetBytes(riskBytes).String()
raw, err := json.Marshal(ethLog)
return PitFileDebtCeilingModel{
What: what,
Data: data,
TransactionIndex: ethLog.TxIndex,
Raw: raw,
}, err
}

View File

@ -0,0 +1,25 @@
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/vulcanize/vulcanizedb/pkg/transformers/shared"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
)
var _ = Describe("", func() {
It("converts a log to an model", func() {
converter := debt_ceiling.PitFileDebtCeilingConverter{}
model, err := converter.ToModel(test_data.PitAddress, shared.PitABI, test_data.EthPitFileDebtCeilingLog)
Expect(err).NotTo(HaveOccurred())
Expect(model.What).To(Equal(test_data.PitFileDebtCeilingModel.What))
Expect(model.Data).To(Equal(test_data.PitFileDebtCeilingModel.Data))
Expect(model.TransactionIndex).To(Equal(test_data.PitFileDebtCeilingModel.TransactionIndex))
Expect(model.Raw).To(Equal(test_data.PitFileDebtCeilingModel.Raw))
Expect(model).To(Equal(test_data.PitFileDebtCeilingModel))
})
})

View File

@ -0,0 +1,13 @@
package debt_ceiling_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestDebtCeiling(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "DebtCeiling Suite")
}

View File

@ -0,0 +1,8 @@
package debt_ceiling
type PitFileDebtCeilingModel struct {
What string
Data string
TransactionIndex uint `db:"tx_idx"`
Raw []byte `db:"raw_log"`
}

View File

@ -0,0 +1,48 @@
package debt_ceiling
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type Repository interface {
Create(headerID int64, model PitFileDebtCeilingModel) 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, model PitFileDebtCeilingModel) error {
_, err := repository.db.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,
)
return err
}
func (repository PitFileDebtCeilingRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
var result []core.Header
err := repository.db.Select(
&result,
`SELECT headers.id, headers.block_number FROM headers
LEFT JOIN maker.pit_file_debt_ceiling on headers.id = header_id
WHERE header_id ISNULL
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
}

View File

@ -0,0 +1,130 @@
package debt_ceiling_test
import (
"database/sql"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("", func() {
Describe("Create", func() {
It("adds a pit file debt ceiling event", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := debt_ceiling.NewPitFileDebtCeilingRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileDebtCeilingModel)
Expect(err).NotTo(HaveOccurred())
var dbPitFile debt_ceiling.PitFileDebtCeilingModel
err = db.Get(&dbPitFile, `SELECT what, data, tx_idx, raw_log FROM maker.pit_file_debt_ceiling WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
Expect(dbPitFile.What).To(Equal(test_data.PitFileDebtCeilingModel.What))
Expect(dbPitFile.Data).To(Equal(test_data.PitFileDebtCeilingModel.Data))
Expect(dbPitFile.TransactionIndex).To(Equal(test_data.PitFileDebtCeilingModel.TransactionIndex))
Expect(dbPitFile.Raw).To(MatchJSON(test_data.PitFileDebtCeilingModel.Raw))
})
It("does not duplicate pit file events", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := debt_ceiling.NewPitFileDebtCeilingRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileDebtCeilingModel)
Expect(err).NotTo(HaveOccurred())
err = pitFileRepository.Create(headerID, test_data.PitFileDebtCeilingModel)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint"))
})
It("removes pit file if corresponding header is deleted", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := debt_ceiling.NewPitFileDebtCeilingRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileDebtCeilingModel)
Expect(err).NotTo(HaveOccurred())
_, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
var dbPitFile debt_ceiling.PitFileDebtCeilingModel
err = db.Get(&dbPitFile, `SELECT what, data, tx_idx, raw_log FROM maker.pit_file_debt_ceiling WHERE header_id = $1`, headerID)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(sql.ErrNoRows))
})
})
Describe("MissingHeaders", func() {
It("returns headers with no associated pit file event", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
startingBlockNumber := int64(1)
pitFileBlockNumber := int64(2)
endingBlockNumber := int64(3)
blockNumbers := []int64{startingBlockNumber, pitFileBlockNumber, endingBlockNumber, endingBlockNumber + 1}
var headerIDs []int64
for _, n := range blockNumbers {
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: n})
headerIDs = append(headerIDs, headerID)
Expect(err).NotTo(HaveOccurred())
}
pitFileRepository := debt_ceiling.NewPitFileDebtCeilingRepository(db)
err := pitFileRepository.Create(headerIDs[1], test_data.PitFileDebtCeilingModel)
Expect(err).NotTo(HaveOccurred())
headers, err := pitFileRepository.MissingHeaders(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
Expect(len(headers)).To(Equal(2))
Expect(headers[0].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
Expect(headers[1].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
})
It("only returns headers associated with the current node", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
blockNumbers := []int64{1, 2, 3}
headerRepository := repositories.NewHeaderRepository(db)
dbTwo := test_config.NewTestDB(core.Node{ID: "second"})
headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo)
var headerIDs []int64
for _, n := range blockNumbers {
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
headerIDs = append(headerIDs, headerID)
_, err = headerRepositoryTwo.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
}
pitFileRepository := debt_ceiling.NewPitFileDebtCeilingRepository(db)
pitFileRepositoryTwo := debt_ceiling.NewPitFileDebtCeilingRepository(dbTwo)
err := pitFileRepository.Create(headerIDs[0], test_data.PitFileDebtCeilingModel)
Expect(err).NotTo(HaveOccurred())
nodeOneMissingHeaders, err := pitFileRepository.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])
Expect(err).NotTo(HaveOccurred())
Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers)))
})
})
})

View File

@ -0,0 +1,57 @@
package debt_ceiling
import (
"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
}
for _, header := range missingHeaders {
topics := [][]common.Hash{{common.HexToHash(shared.PitFileDebtCeilingSignature)}}
matchingLogs, err := transformer.Fetcher.FetchLogs(pit_file.PitFileConfig.ContractAddress, topics, header.BlockNumber)
if err != nil {
return err
}
for _, log := range matchingLogs {
model, err := transformer.Converter.ToModel(pit_file.PitFileConfig.ContractAddress, shared.PitABI, log)
if err != nil {
return err
}
err = transformer.Repository.Create(header.Id, model)
if err != nil {
return err
}
}
}
return nil
}

View File

@ -0,0 +1,162 @@
package debt_ceiling_test
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/transformers/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"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks"
debt_ceiling_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/pit_file/debt_ceiling"
)
var _ = Describe("", 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,
}
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))
})
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2}))
Expect(fetcher.FetchedContractAddress).To(Equal(pit_file.PitFileConfig.ContractAddress))
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(converter.PassedContractAddress).To(Equal(pit_file.PitFileConfig.ContractAddress))
Expect(converter.PassedContractABI).To(Equal(pit_file.PitFileConfig.ContractAbi))
Expect(converter.PassedLog).To(Equal(test_data.EthPitFileDebtCeilingLog))
})
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id))
Expect(repository.PassedModel).To(Equal(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.SetCreateError(fakes.FakeError)
transformer := debt_ceiling.PitFileDebtCeilingTransformer{
Fetcher: fetcher,
Converter: converter,
Repository: repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
})

View File

@ -0,0 +1,31 @@
package ilk
import (
"bytes"
"encoding/json"
"github.com/ethereum/go-ethereum/core/types"
"math/big"
)
type Converter interface {
ToModel(contractAddress string, contractAbi string, ethLog types.Log) (PitFileIlkModel, error)
}
type PitFileIlkConverter struct{}
func (PitFileIlkConverter) ToModel(contractAddress string, contractAbi string, ethLog types.Log) (entity PitFileIlkModel, err error) {
ilk := string(bytes.Trim(ethLog.Topics[2].Bytes(), "\x00"))
what := string(bytes.Trim(ethLog.Topics[3].Bytes(), "\x00"))
itemByteLength := 32
riskBytes := ethLog.Data[len(ethLog.Data)-itemByteLength:]
risk := big.NewInt(0).SetBytes(riskBytes).String()
raw, err := json.Marshal(ethLog)
return PitFileIlkModel{
Ilk: ilk,
What: what,
Data: risk,
TransactionIndex: ethLog.TxIndex,
Raw: raw,
}, err
}

View File

@ -0,0 +1,20 @@
package ilk_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
)
var _ = Describe("Pit file ilk converter", func() {
It("converts a log to an model", func() {
converter := ilk.PitFileIlkConverter{}
model, err := converter.ToModel(test_data.PitAddress, shared.PitABI, test_data.EthPitFileIlkLog)
Expect(err).NotTo(HaveOccurred())
Expect(model).To(Equal(test_data.PitFileIlkModel))
})
})

View File

@ -0,0 +1,13 @@
package ilk_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestIlk(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Ilk Suite")
}

View File

@ -0,0 +1,9 @@
package ilk
type PitFileIlkModel struct {
Ilk string
What string
Data string
TransactionIndex uint `db:"tx_idx"`
Raw []byte `db:"raw_log"`
}

View File

@ -0,0 +1,48 @@
package ilk
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type Repository interface {
Create(headerID int64, model PitFileIlkModel) 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, model PitFileIlkModel) error {
_, err := repository.db.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,
)
return err
}
func (repository PitFileIlkRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
var result []core.Header
err := repository.db.Select(
&result,
`SELECT headers.id, headers.block_number FROM headers
LEFT JOIN maker.pit_file_ilk on headers.id = header_id
WHERE header_id ISNULL
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
}

View File

@ -0,0 +1,129 @@
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/postgres/repositories"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("Pit file ilk repository", func() {
Describe("Create", func() {
It("adds a pit file ilk event", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := ilk.NewPitFileIlkRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileIlkModel)
Expect(err).NotTo(HaveOccurred())
var dbPitFile ilk.PitFileIlkModel
err = db.Get(&dbPitFile, `SELECT ilk, what, data, tx_idx, raw_log FROM maker.pit_file_ilk WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
Expect(dbPitFile.Ilk).To(Equal(test_data.PitFileIlkModel.Ilk))
Expect(dbPitFile.What).To(Equal(test_data.PitFileIlkModel.What))
Expect(dbPitFile.Data).To(Equal(test_data.PitFileIlkModel.Data))
Expect(dbPitFile.TransactionIndex).To(Equal(test_data.PitFileIlkModel.TransactionIndex))
Expect(dbPitFile.Raw).To(MatchJSON(test_data.PitFileIlkModel.Raw))
})
It("does not duplicate pit file ilk events", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := ilk.NewPitFileIlkRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileIlkModel)
Expect(err).NotTo(HaveOccurred())
err = pitFileRepository.Create(headerID, test_data.PitFileIlkModel)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint"))
})
It("removes pit file ilk if corresponding header is deleted", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := ilk.NewPitFileIlkRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileIlkModel)
Expect(err).NotTo(HaveOccurred())
_, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
var dbPitFile ilk.PitFileIlkModel
err = db.Get(&dbPitFile, `SELECT ilk, what, data, tx_idx, raw_log FROM maker.pit_file_ilk WHERE header_id = $1`, headerID)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(sql.ErrNoRows))
})
})
Describe("MissingHeaders", func() {
It("returns headers with no associated pit file ilk event", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
startingBlockNumber := int64(1)
pitFileBlockNumber := int64(2)
endingBlockNumber := int64(3)
blockNumbers := []int64{startingBlockNumber, pitFileBlockNumber, endingBlockNumber, endingBlockNumber + 1}
var headerIDs []int64
for _, n := range blockNumbers {
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: n})
headerIDs = append(headerIDs, headerID)
Expect(err).NotTo(HaveOccurred())
}
pitFileRepository := ilk.NewPitFileIlkRepository(db)
err := pitFileRepository.Create(headerIDs[1], test_data.PitFileIlkModel)
Expect(err).NotTo(HaveOccurred())
headers, err := pitFileRepository.MissingHeaders(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
Expect(len(headers)).To(Equal(2))
Expect(headers[0].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
Expect(headers[1].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
})
It("only returns headers associated with the current node", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
blockNumbers := []int64{1, 2, 3}
headerRepository := repositories.NewHeaderRepository(db)
dbTwo := test_config.NewTestDB(core.Node{ID: "second"})
headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo)
var headerIDs []int64
for _, n := range blockNumbers {
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
headerIDs = append(headerIDs, headerID)
_, err = headerRepositoryTwo.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
}
pitFileRepository := ilk.NewPitFileIlkRepository(db)
pitFileRepositoryTwo := ilk.NewPitFileIlkRepository(dbTwo)
err := pitFileRepository.Create(headerIDs[0], test_data.PitFileIlkModel)
Expect(err).NotTo(HaveOccurred())
nodeOneMissingHeaders, err := pitFileRepository.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])
Expect(err).NotTo(HaveOccurred())
Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers)))
})
})
})

View File

@ -0,0 +1,57 @@
package ilk
import (
"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
}
for _, header := range missingHeaders {
topics := [][]common.Hash{{common.HexToHash(shared.PitFileIlkSignature)}}
matchingLogs, err := transformer.Fetcher.FetchLogs(pit_file.PitFileConfig.ContractAddress, topics, header.BlockNumber)
if err != nil {
return err
}
for _, log := range matchingLogs {
model, err := transformer.Converter.ToModel(pit_file.PitFileConfig.ContractAddress, shared.PitABI, log)
if err != nil {
return err
}
err = transformer.Repository.Create(header.Id, model)
if err != nil {
return err
}
}
}
return nil
}

View File

@ -0,0 +1,162 @@
package ilk_test
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/transformers/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"
)
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,
}
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))
})
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2}))
Expect(fetcher.FetchedContractAddress).To(Equal(pit_file.PitFileConfig.ContractAddress))
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(converter.PassedContractAddress).To(Equal(pit_file.PitFileConfig.ContractAddress))
Expect(converter.PassedContractABI).To(Equal(pit_file.PitFileConfig.ContractAbi))
Expect(converter.PassedLog).To(Equal(test_data.EthPitFileIlkLog))
})
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id))
Expect(repository.PassedModel).To(Equal(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.SetCreateError(fakes.FakeError)
transformer := ilk.PitFileIlkTransformer{
Fetcher: fetcher,
Converter: converter,
Repository: repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
})

View File

@ -0,0 +1,27 @@
package stability_fee
import (
"bytes"
"encoding/json"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type Converter interface {
ToModel(contractAddress string, contractAbi string, ethLog types.Log) (PitFileStabilityFeeModel, error)
}
type PitFileStabilityFeeConverter struct{}
func (PitFileStabilityFeeConverter) ToModel(contractAddress string, contractAbi string, ethLog types.Log) (PitFileStabilityFeeModel, error) {
what := string(bytes.Trim(ethLog.Topics[2].Bytes(), "\x00"))
data := common.HexToAddress(ethLog.Topics[1].String()).Hex()
raw, err := json.Marshal(ethLog)
return PitFileStabilityFeeModel{
What: what,
Data: data,
TransactionIndex: ethLog.TxIndex,
Raw: raw,
}, err
}

View File

@ -0,0 +1,20 @@
package stability_fee_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"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"
)
var _ = Describe("Pit file stability fee converter", func() {
It("converts a log to an model", func() {
converter := stability_fee.PitFileStabilityFeeConverter{}
model, err := converter.ToModel(test_data.PitAddress, shared.PitABI, test_data.EthPitFileStabilityFeeLog)
Expect(err).NotTo(HaveOccurred())
Expect(model).To(Equal(test_data.PitFileStabilityFeeModel))
})
})

View File

@ -0,0 +1,8 @@
package stability_fee
type PitFileStabilityFeeModel struct {
What string
Data string
TransactionIndex uint `db:"tx_idx"`
Raw []byte `db:"raw_log"`
}

View File

@ -0,0 +1,48 @@
package stability_fee
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type Repository interface {
Create(headerID int64, model PitFileStabilityFeeModel) 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, model PitFileStabilityFeeModel) error {
_, err := repository.db.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,
)
return err
}
func (repository PitFileStabilityFeeRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
var result []core.Header
err := repository.db.Select(
&result,
`SELECT headers.id, headers.block_number FROM headers
LEFT JOIN maker.pit_file_stability_fee on headers.id = header_id
WHERE header_id ISNULL
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
}

View File

@ -0,0 +1,130 @@
package stability_fee_test
import (
"database/sql"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee"
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("", func() {
Describe("Create", func() {
It("adds a pit file stability fee event", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := stability_fee.NewPitFileStabilityFeeRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileStabilityFeeModel)
Expect(err).NotTo(HaveOccurred())
var dbPitFile stability_fee.PitFileStabilityFeeModel
err = db.Get(&dbPitFile, `SELECT what, data, tx_idx, raw_log FROM maker.pit_file_stability_fee WHERE header_id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
Expect(dbPitFile.What).To(Equal(test_data.PitFileStabilityFeeModel.What))
Expect(dbPitFile.Data).To(Equal(test_data.PitFileStabilityFeeModel.Data))
Expect(dbPitFile.TransactionIndex).To(Equal(test_data.PitFileStabilityFeeModel.TransactionIndex))
Expect(dbPitFile.Raw).To(MatchJSON(test_data.PitFileStabilityFeeModel.Raw))
})
It("does not duplicate pit file events", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := stability_fee.NewPitFileStabilityFeeRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileStabilityFeeModel)
Expect(err).NotTo(HaveOccurred())
err = pitFileRepository.Create(headerID, test_data.PitFileStabilityFeeModel)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint"))
})
It("removes pit file if corresponding header is deleted", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{})
Expect(err).NotTo(HaveOccurred())
pitFileRepository := stability_fee.NewPitFileStabilityFeeRepository(db)
err = pitFileRepository.Create(headerID, test_data.PitFileStabilityFeeModel)
Expect(err).NotTo(HaveOccurred())
_, err = db.Exec(`DELETE FROM headers WHERE id = $1`, headerID)
Expect(err).NotTo(HaveOccurred())
var dbPitFile stability_fee.PitFileStabilityFeeModel
err = db.Get(&dbPitFile, `SELECT what, data, tx_idx, raw_log FROM maker.pit_file_stability_fee WHERE header_id = $1`, headerID)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(sql.ErrNoRows))
})
})
Describe("MissingHeaders", func() {
It("returns headers with no associated pit file event", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
headerRepository := repositories.NewHeaderRepository(db)
startingBlockNumber := int64(1)
pitFileBlockNumber := int64(2)
endingBlockNumber := int64(3)
blockNumbers := []int64{startingBlockNumber, pitFileBlockNumber, endingBlockNumber, endingBlockNumber + 1}
var headerIDs []int64
for _, n := range blockNumbers {
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: n})
headerIDs = append(headerIDs, headerID)
Expect(err).NotTo(HaveOccurred())
}
pitFileRepository := stability_fee.NewPitFileStabilityFeeRepository(db)
err := pitFileRepository.Create(headerIDs[1], test_data.PitFileStabilityFeeModel)
Expect(err).NotTo(HaveOccurred())
headers, err := pitFileRepository.MissingHeaders(startingBlockNumber, endingBlockNumber)
Expect(err).NotTo(HaveOccurred())
Expect(len(headers)).To(Equal(2))
Expect(headers[0].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
Expect(headers[1].BlockNumber).To(Or(Equal(startingBlockNumber), Equal(endingBlockNumber)))
})
It("only returns headers associated with the current node", func() {
db := test_config.NewTestDB(core.Node{})
test_config.CleanTestDB(db)
blockNumbers := []int64{1, 2, 3}
headerRepository := repositories.NewHeaderRepository(db)
dbTwo := test_config.NewTestDB(core.Node{ID: "second"})
headerRepositoryTwo := repositories.NewHeaderRepository(dbTwo)
var headerIDs []int64
for _, n := range blockNumbers {
headerID, err := headerRepository.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
headerIDs = append(headerIDs, headerID)
_, err = headerRepositoryTwo.CreateOrUpdateHeader(core.Header{BlockNumber: n})
Expect(err).NotTo(HaveOccurred())
}
pitFileRepository := stability_fee.NewPitFileStabilityFeeRepository(db)
pitFileRepositoryTwo := stability_fee.NewPitFileStabilityFeeRepository(dbTwo)
err := pitFileRepository.Create(headerIDs[0], test_data.PitFileStabilityFeeModel)
Expect(err).NotTo(HaveOccurred())
nodeOneMissingHeaders, err := pitFileRepository.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])
Expect(err).NotTo(HaveOccurred())
Expect(len(nodeTwoMissingHeaders)).To(Equal(len(blockNumbers)))
})
})
})

View File

@ -0,0 +1,13 @@
package stability_fee_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestStabilityFee(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "StabilityFee Suite")
}

View File

@ -0,0 +1,57 @@
package stability_fee
import (
"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
}
for _, header := range missingHeaders {
topics := [][]common.Hash{{common.HexToHash(shared.PitFileStabilityFeeSignature)}}
matchingLogs, err := transformer.Fetcher.FetchLogs(pit_file.PitFileConfig.ContractAddress, topics, header.BlockNumber)
if err != nil {
return err
}
for _, log := range matchingLogs {
model, err := transformer.Converter.ToModel(pit_file.PitFileConfig.ContractAddress, shared.PitABI, log)
if err != nil {
return err
}
err = transformer.Repository.Create(header.Id, model)
if err != nil {
return err
}
}
}
return nil
}

View File

@ -0,0 +1,163 @@
package stability_fee_test
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/transformers/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"
stability_fee_mocks "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/mocks/pit_file/stability_fee"
)
var _ = Describe("", 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,
}
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))
})
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())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(fetcher.FetchedBlocks).To(Equal([]int64{1, 2}))
Expect(fetcher.FetchedContractAddress).To(Equal(pit_file.PitFileConfig.ContractAddress))
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(converter.PassedContractAddress).To(Equal(pit_file.PitFileConfig.ContractAddress))
Expect(converter.PassedContractABI).To(Equal(pit_file.PitFileConfig.ContractAbi))
Expect(converter.PassedLog).To(Equal(test_data.EthPitFileStabilityFeeLog))
})
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,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
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,
}
err := transformer.Execute()
Expect(err).NotTo(HaveOccurred())
Expect(repository.PassedHeaderID).To(Equal(fakeHeader.Id))
Expect(repository.PassedModel).To(Equal(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.SetCreateError(fakes.FakeError)
transformer := stability_fee.PitFileStabilityFeeTransformer{
Fetcher: fetcher,
Converter: converter,
Repository: repository,
}
err := transformer.Execute()
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(fakes.FakeError))
})
})

View File

@ -22,7 +22,5 @@ import (
var ( var (
ErrNoMatchingLog = errors.New("no matching log") ErrNoMatchingLog = errors.New("no matching log")
Ether = big.NewFloat(1e18) Ether = big.NewFloat(1e18)
LogValueTopic0 = "0x296ba4ca62c6c21c95e828080cb8aec7481b71390585605300a8a76f9e95b527"
MedianizerABI = `[{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"","type":"bytes32"}],"name":"poke","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"poke","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"compute","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"wat","type":"address"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wat","type":"address"}],"name":"unset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"indexes","outputs":[{"name":"","type":"bytes12"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"next","outputs":[{"name":"","type":"bytes12"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"read","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"peek","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes12"}],"name":"values","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"min_","type":"uint96"}],"name":"setMin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"void","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pos","type":"bytes12"},{"name":"wat","type":"address"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"pos","type":"bytes12"}],"name":"unset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"next_","type":"bytes12"}],"name":"setNext","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"min","outputs":[{"name":"","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"val","type":"bytes32"}],"name":"LogValue","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"}]]`
Ray = big.NewFloat(1e27) Ray = big.NewFloat(1e27)
) )

View File

@ -21,6 +21,7 @@ import (
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds" "github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
) )
var _ = Describe("Price feed converter", func() { var _ = Describe("Price feed converter", func() {
@ -31,7 +32,7 @@ var _ = Describe("Price feed converter", func() {
// https://etherscan.io/tx/0xa51a50a2adbfba4e2ab3d72dfd67a21c769f1bc8d2b180663a15500a56cde58f // https://etherscan.io/tx/0xa51a50a2adbfba4e2ab3d72dfd67a21c769f1bc8d2b180663a15500a56cde58f
log := types.Log{ log := types.Log{
Address: medianizerAddress, Address: medianizerAddress,
Topics: []common.Hash{common.HexToHash(price_feeds.LogValueTopic0)}, Topics: []common.Hash{common.HexToHash(shared.LogValueSignature)},
Data: common.FromHex("00000000000000000000000000000000000000000000001486f658319fb0c100"), Data: common.FromHex("00000000000000000000000000000000000000000000001486f658319fb0c100"),
BlockNumber: blockNumber, BlockNumber: blockNumber,
TxHash: common.HexToHash("0xa51a50a2adbfba4e2ab3d72dfd67a21c769f1bc8d2b180663a15500a56cde58f"), TxHash: common.HexToHash("0xa51a50a2adbfba4e2ab3d72dfd67a21c769f1bc8d2b180663a15500a56cde58f"),

View File

@ -19,6 +19,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/vulcanizedb/pkg/core" "github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
"math/big" "math/big"
) )
@ -48,7 +49,7 @@ func (fetcher PriceFeedFetcher) FetchLogValues(blockNumber int64) ([]types.Log,
FromBlock: n, FromBlock: n,
ToBlock: n, ToBlock: n,
Addresses: addresses, Addresses: addresses,
Topics: [][]common.Hash{{common.HexToHash(LogValueTopic0)}}, Topics: [][]common.Hash{{common.HexToHash(shared.LogValueSignature)}},
} }
return fetcher.blockChain.GetEthLogsWithCustomQuery(query) return fetcher.blockChain.GetEthLogsWithCustomQuery(query)
} }

View File

@ -25,6 +25,7 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/fakes" "github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds" "github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
) )
var _ = Describe("Price fetcher", func() { var _ = Describe("Price fetcher", func() {
@ -46,7 +47,7 @@ var _ = Describe("Price fetcher", func() {
FromBlock: big.NewInt(blockNumber), FromBlock: big.NewInt(blockNumber),
ToBlock: big.NewInt(blockNumber), ToBlock: big.NewInt(blockNumber),
Addresses: expectedAddresses, Addresses: expectedAddresses,
Topics: [][]common.Hash{{common.HexToHash(price_feeds.LogValueTopic0)}}, Topics: [][]common.Hash{{common.HexToHash(shared.LogValueSignature)}},
} }
mockBlockChain.AssertGetEthLogsWithCustomQueryCalledWith(expectedQuery) mockBlockChain.AssertGetEthLogsWithCustomQueryCalledWith(expectedQuery)
}) })

View File

@ -15,9 +15,27 @@
package shared package shared
var ( var (
biteMethod = "Bite(bytes32,bytes32,uint256,uint256,uint256,uint256,uint256)"
flipKickMethod = "Kick(uint256,uint256,uint256,address,uint48,bytes32,uint256)"
frobMethod = "Frob(bytes32,bytes32,uint256,uint256,int256,int256,uint256)"
pitFileDebtCeilingMethod = "file(bytes32,uint256)"
pitFileIlkMethod = "file(bytes32,bytes32,uint256)"
pitFileStabilityFeeMethod = "file(bytes32,address)"
tendMethod = "tend(uint256,uint256,uint256)"
CatABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"vat\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vow\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"flips\",\"outputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"lad\",\"type\":\"bytes32\"},{\"name\":\"ink\",\"type\":\"uint256\"},{\"name\":\"tab\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nflip\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"live\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"wards\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"ilks\",\"outputs\":[{\"name\":\"flip\",\"type\":\"address\"},{\"name\":\"chop\",\"type\":\"uint256\"},{\"name\":\"lump\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pit\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"vat_\",\"type\":\"address\"},{\"name\":\"pit_\",\"type\":\"address\"},{\"name\":\"vow_\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"ilk\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"lad\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ink\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"art\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"tab\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"flip\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"iArt\",\"type\":\"uint256\"}],\"name\":\"Bite\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":true,\"name\":\"sig\",\"type\":\"bytes4\"},{\"indexed\":true,\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"foo\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"bar\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"wad\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"fax\",\"type\":\"bytes\"}],\"name\":\"LogNote\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[{\"name\":\"guy\",\"type\":\"address\"}],\"name\":\"rely\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"guy\",\"type\":\"address\"}],\"name\":\"deny\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"what\",\"type\":\"bytes32\"},{\"name\":\"data\",\"type\":\"uint256\"}],\"name\":\"file\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"what\",\"type\":\"bytes32\"},{\"name\":\"flip\",\"type\":\"address\"}],\"name\":\"file\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ilk\",\"type\":\"bytes32\"},{\"name\":\"lad\",\"type\":\"bytes32\"}],\"name\":\"bite\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"n\",\"type\":\"uint256\"},{\"name\":\"wad\",\"type\":\"uint256\"}],\"name\":\"flip\",\"outputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"
FlipperABI = `[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"bids","outputs":[{"name":"bid","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"guy","type":"address"},{"name":"tic","type":"uint48"},{"name":"end","type":"uint48"},{"name":"urn","type":"bytes32"},{"name":"gal","type":"address"},{"name":"tab","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x4423c5f1"},{"constant":true,"inputs":[],"name":"ttl","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x4e8b1dd5"},{"constant":true,"inputs":[],"name":"gem","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x7bd2bea7"},{"constant":true,"inputs":[],"name":"beg","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x7d780d82"},{"constant":true,"inputs":[],"name":"tau","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xcfc4af55"},{"constant":true,"inputs":[],"name":"kicks","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xcfdd3302"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xf4b9fa75"},{"inputs":[{"name":"dai_","type":"address"},{"name":"gem_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"lot","type":"uint256"},{"indexed":false,"name":"bid","type":"uint256"},{"indexed":false,"name":"gal","type":"address"},{"indexed":false,"name":"end","type":"uint48"},{"indexed":true,"name":"urn","type":"bytes32"},{"indexed":false,"name":"tab","type":"uint256"}],"name":"Kick","type":"event","signature":"0xbac86238bdba81d21995024470425ecb370078fa62b7271b90cf28cbd1e3e87e"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event","signature":"0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31"},{"constant":true,"inputs":[],"name":"era","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x143e55e0"},{"constant":false,"inputs":[{"name":"urn","type":"bytes32"},{"name":"gal","type":"address"},{"name":"tab","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"kick","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xeae19d9e"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"tick","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xfc7b6aee"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"tend","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x4b43ed12"},{"constant":false,"inputs":[{"name":"id","type":"uint256"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"dent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x5ff3a382"},{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"deal","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xc959c42b"}]`
MedianizerABI = `[{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"","type":"bytes32"}],"name":"poke","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"poke","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"compute","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"wat","type":"address"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wat","type":"address"}],"name":"unset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"indexes","outputs":[{"name":"","type":"bytes12"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"next","outputs":[{"name":"","type":"bytes12"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"read","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"peek","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes12"}],"name":"values","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"min_","type":"uint96"}],"name":"setMin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"void","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"pos","type":"bytes12"},{"name":"wat","type":"address"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"pos","type":"bytes12"}],"name":"unset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"next_","type":"bytes12"}],"name":"setNext","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"min","outputs":[{"name":"","type":"uint96"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"val","type":"bytes32"}],"name":"LogValue","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"}]]`
PitABI = `[{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x36569e77"},{"constant":true,"inputs":[],"name":"live","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x957aa58c"},{"constant":true,"inputs":[],"name":"drip","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x9f678cca"},{"constant":true,"inputs":[],"name":"Line","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xbabe8a3f"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xbf353dbb"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"ilks","outputs":[{"name":"spot","type":"uint256"},{"name":"line","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd9638d36"},{"inputs":[{"name":"vat_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"ilk","type":"bytes32"},{"indexed":true,"name":"urn","type":"bytes32"},{"indexed":false,"name":"ink","type":"uint256"},{"indexed":false,"name":"art","type":"uint256"},{"indexed":false,"name":"dink","type":"int256"},{"indexed":false,"name":"dart","type":"int256"},{"indexed":false,"name":"iArt","type":"uint256"}],"name":"Frob","type":"event","signature":"0xb2afa28318bcc689926b52835d844de174ef8de97e982a85c0199d584920791b"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event","signature":"0x644843f351d3fba4abcd60109eaff9f54bac8fb8ccf0bab941009c21df21cf31"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x65fae35e"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x9c52a7f1"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x1a0b287e"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"uint256"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x29ae8114"},{"constant":false,"inputs":[{"name":"what","type":"bytes32"},{"name":"data","type":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xd4e8be83"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"dink","type":"int256"},{"name":"dart","type":"int256"}],"name":"frob","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x5a984ded"}]`
FlipperContractAddress = "0x6b59c42097e2fff7cad96cb08ceefd601081ad9c" //this is a temporary address deployed locally FlipperContractAddress = "0x6b59c42097e2fff7cad96cb08ceefd601081ad9c" //this is a temporary address deployed locally
FlipperABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"era\",\"outputs\":[{\"name\":\"\",\"type\":\"uint48\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"bids\",\"outputs\":[{\"name\":\"bid\",\"type\":\"uint256\"},{\"name\":\"lot\",\"type\":\"uint256\"},{\"name\":\"guy\",\"type\":\"address\"},{\"name\":\"tic\",\"type\":\"uint48\"},{\"name\":\"end\",\"type\":\"uint48\"},{\"name\":\"urn\",\"type\":\"bytes32\"},{\"name\":\"gal\",\"type\":\"address\"},{\"name\":\"tab\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"name\":\"lot\",\"type\":\"uint256\"},{\"name\":\"bid\",\"type\":\"uint256\"}],\"name\":\"tend\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ttl\",\"outputs\":[{\"name\":\"\",\"type\":\"uint48\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"name\":\"lot\",\"type\":\"uint256\"},{\"name\":\"bid\",\"type\":\"uint256\"}],\"name\":\"dent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"gem\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"beg\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"deal\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"tau\",\"outputs\":[{\"name\":\"\",\"type\":\"uint48\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"kicks\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"urn\",\"type\":\"bytes32\"},{\"name\":\"gal\",\"type\":\"address\"},{\"name\":\"tab\",\"type\":\"uint256\"},{\"name\":\"lot\",\"type\":\"uint256\"},{\"name\":\"bid\",\"type\":\"uint256\"}],\"name\":\"kick\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"dai\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"tick\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"dai_\",\"type\":\"address\"},{\"name\":\"gem_\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"lot\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"bid\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"gal\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"end\",\"type\":\"uint48\"},{\"indexed\":true,\"name\":\"urn\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"tab\",\"type\":\"uint256\"}],\"name\":\"Kick\",\"type\":\"event\"},{\"anonymous\":true,\"inputs\":[{\"indexed\":true,\"name\":\"sig\",\"type\":\"bytes4\"},{\"indexed\":true,\"name\":\"guy\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"foo\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"bar\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"wad\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"fax\",\"type\":\"bytes\"}],\"name\":\"LogNote\",\"type\":\"event\"}]"
FlipKickSignature = "0xbac86238bdba81d21995024470425ecb370078fa62b7271b90cf28cbd1e3e87e" BiteSignature = GetEventSignature(biteMethod)
BiteSignature = "0x44a8f29dfcf27e5dd7a4db50b390f851bf3ecf2bf221243be3e853f586134455" FlipKickSignature = GetEventSignature(flipKickMethod)
TendFunctionSignature = "0x4b43ed1200000000000000000000000000000000000000000000000000000000" FrobSignature = GetEventSignature(frobMethod)
LogValueSignature = GetEventSignature("")
PitFileDebtCeilingSignature = GetLogNoteSignature(pitFileDebtCeilingMethod)
PitFileIlkSignature = GetLogNoteSignature(pitFileIlkMethod)
PitFileStabilityFeeSignature = GetLogNoteSignature(pitFileStabilityFeeMethod)
TendFunctionSignature = GetLogNoteSignature(tendMethod)
) )

View File

@ -0,0 +1,14 @@
package shared
import "github.com/ethereum/go-ethereum/crypto"
func GetEventSignature(solidityMethodSignature string) string {
eventSignature := []byte(solidityMethodSignature)
hash := crypto.Keccak256Hash(eventSignature)
return hash.Hex()
}
func GetLogNoteSignature(solidityMethodSignature string) string {
rawSignature := GetEventSignature(solidityMethodSignature)
return rawSignature[:10] + "00000000000000000000000000000000000000000000000000000000"
}

View File

@ -0,0 +1,69 @@
package shared_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
)
var _ = Describe("Event signature generator", func() {
Describe("generating non-anonymous event signatures", func() {
It("generates bite event signature", func() {
expected := "0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"
actual := shared.GetEventSignature("Bite(bytes32,bytes32,uint256,uint256,uint256,uint256,uint256)")
Expect(expected).To(Equal(actual))
})
It("generates frob event signature", func() {
expected := "0xb2afa28318bcc689926b52835d844de174ef8de97e982a85c0199d584920791b"
actual := shared.GetEventSignature("Frob(bytes32,bytes32,uint256,uint256,int256,int256,uint256)")
Expect(expected).To(Equal(actual))
})
It("generates flip kick event signature", func() {
expected := "0xbac86238bdba81d21995024470425ecb370078fa62b7271b90cf28cbd1e3e87e"
actual := shared.GetEventSignature("Kick(uint256,uint256,uint256,address,uint48,bytes32,uint256)")
Expect(expected).To(Equal(actual))
})
It("generates log value event signature", func() {
expected := "0x296ba4ca62c6c21c95e828080cb8aec7481b71390585605300a8a76f9e95b527"
actual := shared.GetEventSignature("LogValue(bytes32)")
Expect(expected).To(Equal(actual))
})
})
Describe("generating LogNote event signatures", func() {
It("generates flip tend event signature", func() {
expected := "0x4b43ed1200000000000000000000000000000000000000000000000000000000"
actual := shared.GetLogNoteSignature("tend(uint256,uint256,uint256)")
Expect(expected).To(Equal(actual))
})
It("generates pit file event signature for overloaded function with three arguments", func() {
expected := "0x1a0b287e00000000000000000000000000000000000000000000000000000000"
actual := shared.GetLogNoteSignature("file(bytes32,bytes32,uint256)")
Expect(expected).To(Equal(actual))
})
It("generates pit file event signature for overloaded function with two arguments", func() {
expected := "0x29ae811400000000000000000000000000000000000000000000000000000000"
actual := shared.GetLogNoteSignature("file(bytes32,uint256)")
Expect(expected).To(Equal(actual))
})
It("generates pit file event signature for overloaded function with two different arguments", func() {
expected := "0xd4e8be8300000000000000000000000000000000000000000000000000000000"
actual := shared.GetLogNoteSignature("file(bytes32,address)")
Expect(expected).To(Equal(actual))
})
})
})

View File

@ -28,7 +28,7 @@ type Transformer interface {
type TransformerInitializer func(db *postgres.DB, blockChain core.BlockChain) Transformer type TransformerInitializer func(db *postgres.DB, blockChain core.BlockChain) Transformer
type TransformerConfig struct { type TransformerConfig struct {
ContractAddresses string ContractAddress string
ContractAbi string ContractAbi string
Topics []string Topics []string
StartingBlockNumber int64 StartingBlockNumber int64

View File

@ -17,7 +17,7 @@ package tend
import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
var TendConfig = shared.TransformerConfig{ var TendConfig = shared.TransformerConfig{
ContractAddresses: shared.FlipperContractAddress, ContractAddress: shared.FlipperContractAddress,
ContractAbi: shared.FlipperABI, ContractAbi: shared.FlipperABI,
Topics: []string{shared.TendFunctionSignature}, Topics: []string{shared.TendFunctionSignature},
StartingBlockNumber: 0, StartingBlockNumber: 0,

View File

@ -59,14 +59,14 @@ func (t TendTransformer) Execute() error {
} }
for _, header := range missingHeaders { for _, header := range missingHeaders {
ethLogs, err := t.Fetcher.FetchLogs(config.ContractAddresses, topics, header.BlockNumber) ethLogs, err := t.Fetcher.FetchLogs(config.ContractAddress, topics, header.BlockNumber)
if err != nil { if err != nil {
log.Println("Error fetching matching logs:", err) log.Println("Error fetching matching logs:", err)
return err return err
} }
for _, ethLog := range ethLogs { for _, ethLog := range ethLogs {
model, err := t.Converter.Convert(config.ContractAddresses, config.ContractAbi, ethLog) model, err := t.Converter.Convert(config.ContractAddress, config.ContractAbi, ethLog)
if err != nil { if err != nil {
log.Println("Error converting logs:", err) log.Println("Error converting logs:", err)
return err return err

View File

@ -93,7 +93,7 @@ var _ = Describe("Tend Transformer", func() {
err := transformer.Execute() err := transformer.Execute()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
Expect(converter.ConverterContract).To(Equal(tend.TendConfig.ContractAddresses)) Expect(converter.ConverterContract).To(Equal(tend.TendConfig.ContractAddress))
Expect(converter.ConverterAbi).To(Equal(tend.TendConfig.ContractAbi)) Expect(converter.ConverterAbi).To(Equal(tend.TendConfig.ContractAbi))
Expect(converter.LogsToConvert).To(Equal([]types.Log{test_data.TendLogNote})) Expect(converter.LogsToConvert).To(Equal([]types.Log{test_data.TendLogNote}))
}) })

View File

@ -15,6 +15,7 @@
package test_data package test_data
import ( import (
"encoding/json"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -59,21 +60,26 @@ var EthFrobLog = types.Log{
} }
var FrobEntity = frob.FrobEntity{ var FrobEntity = frob.FrobEntity{
Ilk: ilk, Ilk: ilk,
Lad: frobLad, Urn: frobLad,
Dink: dink, Ink: ink,
Dart: dart, Art: art,
Ink: ink, Dink: dink,
Art: art, Dart: dart,
IArt: iArt, IArt: iArt,
TransactionIndex: EthFrobLog.TxIndex,
Raw: EthFrobLog,
} }
var rawFrobLog, _ = json.Marshal(EthFrobLog)
var FrobModel = frob.FrobModel{ var FrobModel = frob.FrobModel{
Ilk: ilk[:], Ilk: ilk[:],
Lad: frobLad[:], Urn: frobLad[:],
Dink: dink.String(), Ink: ink.String(),
Dart: dart.String(), Art: art.String(),
Ink: ink.String(), Dink: dink.String(),
Art: art.String(), Dart: dart.String(),
IArt: iArt.String(), IArt: iArt.String(),
TransactionIndex: EthFrobLog.TxIndex,
Raw: rawFrobLog,
} }

View File

@ -25,21 +25,26 @@ type MockFrobConverter struct {
PassedContractABI string PassedContractABI string
PassedLog types.Log PassedLog types.Log
PassedEntity frob.FrobEntity PassedEntity frob.FrobEntity
converterError error toEntityError error
toModelError error
} }
func (converter *MockFrobConverter) SetConverterError(err error) { func (converter *MockFrobConverter) SetToEntityError(err error) {
converter.converterError = err converter.toEntityError = err
}
func (converter *MockFrobConverter) SetToModelError(err error) {
converter.toModelError = err
} }
func (converter *MockFrobConverter) ToEntity(contractAddress string, contractAbi string, ethLog types.Log) (frob.FrobEntity, error) { func (converter *MockFrobConverter) ToEntity(contractAddress string, contractAbi string, ethLog types.Log) (frob.FrobEntity, error) {
converter.PassedContractAddress = contractAddress converter.PassedContractAddress = contractAddress
converter.PassedContractABI = contractAbi converter.PassedContractABI = contractAbi
converter.PassedLog = ethLog converter.PassedLog = ethLog
return test_data.FrobEntity, converter.converterError return test_data.FrobEntity, converter.toEntityError
} }
func (converter *MockFrobConverter) ToModel(frobEntity frob.FrobEntity) frob.FrobModel { func (converter *MockFrobConverter) ToModel(frobEntity frob.FrobEntity) (frob.FrobModel, error) {
converter.PassedEntity = frobEntity converter.PassedEntity = frobEntity
return test_data.FrobModel return test_data.FrobModel, converter.toModelError
} }

View File

@ -25,7 +25,6 @@ type MockFrobRepository struct {
PassedFrobModel frob.FrobModel PassedFrobModel frob.FrobModel
PassedHeaderID int64 PassedHeaderID int64
PassedStartingBlockNumber int64 PassedStartingBlockNumber int64
PassedTransactionIndex uint
missingHeaders []core.Header missingHeaders []core.Header
missingHeadersErr error missingHeadersErr error
} }
@ -42,9 +41,8 @@ func (repository *MockFrobRepository) SetMissingHeaders(headers []core.Header) {
repository.missingHeaders = headers repository.missingHeaders = headers
} }
func (repository *MockFrobRepository) Create(headerID int64, transactionIndex uint, model frob.FrobModel) error { func (repository *MockFrobRepository) Create(headerID int64, model frob.FrobModel) error {
repository.PassedHeaderID = headerID repository.PassedHeaderID = headerID
repository.PassedTransactionIndex = transactionIndex
repository.PassedFrobModel = model repository.PassedFrobModel = model
return repository.createError return repository.createError
} }

View File

@ -0,0 +1,25 @@
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
PassedContractAddress string
PassedContractABI string
PassedLog types.Log
}
func (converter *MockPitFileDebtCeilingConverter) ToModel(contractAddress string, contractAbi string, ethLog types.Log) (debt_ceiling.PitFileDebtCeilingModel, error) {
converter.PassedContractAddress = contractAddress
converter.PassedContractABI = contractAbi
converter.PassedLog = ethLog
return test_data.PitFileDebtCeilingModel, converter.converterErr
}
func (converter *MockPitFileDebtCeilingConverter) SetConverterError(e error) {
converter.converterErr = e
}

View File

@ -0,0 +1,40 @@
package debt_ceiling
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling"
)
type MockPitFileDebtCeilingRepository struct {
createErr error
missingHeaders []core.Header
missingHeadersErr error
PassedStartingBlockNumber int64
PassedEndingBlockNumber int64
PassedHeaderID int64
PassedModel debt_ceiling.PitFileDebtCeilingModel
}
func (repository *MockPitFileDebtCeilingRepository) Create(headerID int64, model debt_ceiling.PitFileDebtCeilingModel) error {
repository.PassedHeaderID = headerID
repository.PassedModel = model
return repository.createErr
}
func (repository *MockPitFileDebtCeilingRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
repository.PassedStartingBlockNumber = startingBlockNumber
repository.PassedEndingBlockNumber = endingBlockNumber
return repository.missingHeaders, repository.missingHeadersErr
}
func (repository *MockPitFileDebtCeilingRepository) SetMissingHeadersErr(e error) {
repository.missingHeadersErr = e
}
func (repository *MockPitFileDebtCeilingRepository) SetMissingHeaders(headers []core.Header) {
repository.missingHeaders = headers
}
func (repository *MockPitFileDebtCeilingRepository) SetCreateError(e error) {
repository.createErr = e
}

View File

@ -0,0 +1,26 @@
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"
)
type MockPitFileIlkConverter struct {
PassedContractAddress string
PassedContractABI string
PassedLog types.Log
converterError error
}
func (converter *MockPitFileIlkConverter) SetConverterError(err error) {
converter.converterError = err
}
func (converter *MockPitFileIlkConverter) ToModel(contractAddress string, contractAbi string, ethLog types.Log) (ilk.PitFileIlkModel, error) {
converter.PassedContractAddress = contractAddress
converter.PassedContractABI = contractAbi
converter.PassedLog = ethLog
return test_data.PitFileIlkModel, converter.converterError
}

View File

@ -0,0 +1,40 @@
package ilk
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk"
)
type MockPitFileIlkRepository struct {
createError error
PassedEndingBlockNumber int64
PassedModel ilk.PitFileIlkModel
PassedHeaderID int64
PassedStartingBlockNumber int64
missingHeaders []core.Header
missingHeadersErr error
}
func (repository *MockPitFileIlkRepository) SetCreateError(err error) {
repository.createError = err
}
func (repository *MockPitFileIlkRepository) SetMissingHeadersErr(err error) {
repository.missingHeadersErr = err
}
func (repository *MockPitFileIlkRepository) SetMissingHeaders(headers []core.Header) {
repository.missingHeaders = headers
}
func (repository *MockPitFileIlkRepository) Create(headerID int64, model ilk.PitFileIlkModel) error {
repository.PassedHeaderID = headerID
repository.PassedModel = model
return repository.createError
}
func (repository *MockPitFileIlkRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
repository.PassedStartingBlockNumber = startingBlockNumber
repository.PassedEndingBlockNumber = endingBlockNumber
return repository.missingHeaders, repository.missingHeadersErr
}

View File

@ -0,0 +1,25 @@
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
PassedContractAddress string
PassedContractABI string
PassedLog types.Log
}
func (converter *MockPitFileStabilityFeeConverter) ToModel(contractAddress string, contractAbi string, ethLog types.Log) (stability_fee.PitFileStabilityFeeModel, error) {
converter.PassedContractAddress = contractAddress
converter.PassedContractABI = contractAbi
converter.PassedLog = ethLog
return test_data.PitFileStabilityFeeModel, converter.converterErr
}
func (converter *MockPitFileStabilityFeeConverter) SetConverterError(e error) {
converter.converterErr = e
}

View File

@ -0,0 +1,38 @@
package stability_fee
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee"
)
type MockPitFileStabilityFeeRepository struct {
createErr error
missingHeaders []core.Header
missingHeadersErr error
PassedStartingBlockNumber int64
PassedEndingBlockNumber int64
PassedHeaderID int64
PassedModel stability_fee.PitFileStabilityFeeModel
}
func (repository *MockPitFileStabilityFeeRepository) Create(headerID int64, model stability_fee.PitFileStabilityFeeModel) error {
repository.PassedModel = model
repository.PassedHeaderID = headerID
return repository.createErr
}
func (repository *MockPitFileStabilityFeeRepository) MissingHeaders(startingBlockNumber, endingBlockNumber int64) ([]core.Header, error) {
repository.PassedStartingBlockNumber = startingBlockNumber
repository.PassedEndingBlockNumber = endingBlockNumber
return repository.missingHeaders, repository.missingHeadersErr
}
func (repository *MockPitFileStabilityFeeRepository) SetMissingHeadersErr(e error) {
repository.missingHeadersErr = e
}
func (repository *MockPitFileStabilityFeeRepository) SetMissingHeaders(headers []core.Header) {
repository.missingHeaders = headers
}
func (repository *MockPitFileStabilityFeeRepository) SetCreateError(e error) {
repository.createErr = e
}

View File

@ -0,0 +1,92 @@
package test_data
import (
"encoding/json"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/debt_ceiling"
ilk2 "github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/ilk"
"github.com/vulcanize/vulcanizedb/pkg/transformers/pit_file/stability_fee"
"math/big"
)
var (
PitAddress = "0xff3f2400f1600f3f493a9a92704a29b96795af1a"
)
var EthPitFileDebtCeilingLog = types.Log{
Address: common.HexToAddress(PitAddress),
Topics: []common.Hash{
common.HexToHash("0x29ae811400000000000000000000000000000000000000000000000000000000"),
common.HexToHash("0x00000000000000000000000064d922894153be9eef7b7218dc565d1d0ce2a092"),
common.HexToHash("0x6472697000000000000000000000000000000000000000000000000000000000"),
common.HexToHash("0x000000000000000000000000000000000000000000000000000000000000007b"),
},
Data: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004429ae81146472697000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b"),
BlockNumber: 22,
TxHash: common.HexToHash("0xd744878a0b6655e3ba729e1019f56b563b4a16750196b8ad6104f3977db43f42"),
TxIndex: 333,
BlockHash: common.HexToHash("0xa54d9d99c315bea3dda7256a36e51773ed009a01c0859295c5382d4b83d7eeb9"),
Index: 0,
Removed: false,
}
var rawPitFileDebtCeilingLog, _ = json.Marshal(EthPitFileDebtCeilingLog)
var PitFileDebtCeilingModel = debt_ceiling.PitFileDebtCeilingModel{
What: "0x64d922894153BE9EEf7b7218dc565d1D0Ce2a092",
Data: big.NewInt(123).String(),
TransactionIndex: EthPitFileDebtCeilingLog.TxIndex,
Raw: rawPitFileDebtCeilingLog,
}
var EthPitFileIlkLog = types.Log{
Address: common.HexToAddress(PitAddress),
Topics: []common.Hash{
common.HexToHash("0x1a0b287e00000000000000000000000000000000000000000000000000000000"),
common.HexToHash("0x0000000000000000000000000f243e26db94b5426032e6dfa6007802dea2a614"),
common.HexToHash("0x66616b6520696c6b000000000000000000000000000000000000000000000000"),
common.HexToHash("0x73706f7400000000000000000000000000000000000000000000000000000000"),
},
Data: hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000641a0b287e66616b6520696c6b00000000000000000000000000000000000000000000000073706f7400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007b"),
BlockNumber: 11,
TxHash: common.HexToHash("0x1ba8125f60fa045c85b35df3983bee37db8627fbc32e3442a5cf17c85bb83f09"),
TxIndex: 111,
BlockHash: common.HexToHash("0x6dc284247c524b22b10a75ef1c9d1709a509208d04c15fa2b675a293db637d21"),
Index: 0,
Removed: false,
}
var rawPitFileIlkLog, _ = json.Marshal(EthPitFileIlkLog)
var PitFileIlkModel = ilk2.PitFileIlkModel{
Ilk: "fake ilk",
What: "spot",
Data: big.NewInt(123).String(),
TransactionIndex: EthPitFileIlkLog.TxIndex,
Raw: rawPitFileIlkLog,
}
var EthPitFileStabilityFeeLog = types.Log{
Address: common.HexToAddress("0x6b59c42097e2Fff7cad96cb08cEeFd601081aD9c"),
Topics: []common.Hash{
common.HexToHash("0xd4e8be8300000000000000000000000000000000000000000000000000000000"),
common.HexToHash("0x00000000000000000000000064d922894153be9eef7b7218dc565d1d0ce2a092"),
common.HexToHash("0x6472697000000000000000000000000000000000000000000000000000000000"),
common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
},
Data: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000044d4e8be8364726970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
BlockNumber: 12,
TxHash: common.HexToHash("0x78cdc62316ccf8e31515d09745cc724f557569f01a557d0d09b1066bf7079fd2"),
TxIndex: 222,
BlockHash: common.HexToHash("0xe3d8e458421533170871b4033f978a3793ef10b7e33a9328a13c09e2fd90208d"),
Index: 0,
Removed: false,
}
var rawPitFileStabilityFeeLog, _ = json.Marshal(EthPitFileStabilityFeeLog)
var PitFileStabilityFeeModel = stability_fee.PitFileStabilityFeeModel{
What: "drip",
Data: "0x64d922894153BE9EEf7b7218dc565d1D0Ce2a092",
TransactionIndex: EthPitFileStabilityFeeLog.TxIndex,
Raw: rawPitFileStabilityFeeLog,
}

View File

@ -18,6 +18,10 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/transformers/bite" "github.com/vulcanize/vulcanizedb/pkg/transformers/bite"
"github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick"
"github.com/vulcanize/vulcanizedb/pkg/transformers/frob" "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"
"github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds" "github.com/vulcanize/vulcanizedb/pkg/transformers/price_feeds"
"github.com/vulcanize/vulcanizedb/pkg/transformers/shared" "github.com/vulcanize/vulcanizedb/pkg/transformers/shared"
"github.com/vulcanize/vulcanizedb/pkg/transformers/tend" "github.com/vulcanize/vulcanizedb/pkg/transformers/tend"
@ -28,6 +32,10 @@ func TransformerInitializers() []shared.TransformerInitializer {
flipKickTransformerInitializer := flip_kick.FlipKickTransformerInitializer{Config: flipKickConfig} flipKickTransformerInitializer := flip_kick.FlipKickTransformerInitializer{Config: flipKickConfig}
frobConfig := frob.FrobConfig frobConfig := frob.FrobConfig
frobTransformerInitializer := frob.FrobTransformerInitializer{Config: frobConfig} frobTransformerInitializer := frob.FrobTransformerInitializer{Config: frobConfig}
pitFileConfig := pit_file.PitFileConfig
pitFileDebtCeilingTransformerInitializer := debt_ceiling.PitFileDebtCeilingTransformerInitializer{Config: pitFileConfig}
pitFileIlkTransformerInitializer := ilk.PitFileIlkTransformerInitializer{Config: pitFileConfig}
pitFileStabilityFeeTransformerInitializer := stability_fee.PitFileStabilityFeeTransformerInitializer{Config: pitFileConfig}
priceFeedConfig := price_feeds.PriceFeedConfig priceFeedConfig := price_feeds.PriceFeedConfig
priceFeedTransformerInitializer := price_feeds.PriceFeedTransformerInitializer{Config: priceFeedConfig} priceFeedTransformerInitializer := price_feeds.PriceFeedTransformerInitializer{Config: priceFeedConfig}
tendConfig := tend.TendConfig tendConfig := tend.TendConfig
@ -38,6 +46,9 @@ func TransformerInitializers() []shared.TransformerInitializer {
biteTransformerInitializer.NewBiteTransformer, biteTransformerInitializer.NewBiteTransformer,
flipKickTransformerInitializer.NewFlipKickTransformer, flipKickTransformerInitializer.NewFlipKickTransformer,
frobTransformerInitializer.NewFrobTransformer, frobTransformerInitializer.NewFrobTransformer,
pitFileDebtCeilingTransformerInitializer.NewPitFileDebtCeilingTransformer,
pitFileIlkTransformerInitializer.NewPitFileIlkTransformer,
pitFileStabilityFeeTransformerInitializer.NewPitFileStabilityFeeTransformer,
priceFeedTransformerInitializer.NewPriceFeedTransformer, priceFeedTransformerInitializer.NewPriceFeedTransformer,
tendTransformerInitializer.NewTendTransformer, tendTransformerInitializer.NewTendTransformer,
} }

View File

@ -77,6 +77,8 @@ func CleanTestDB(db *postgres.DB) {
db.MustExec("DELETE FROM headers") db.MustExec("DELETE FROM headers")
db.MustExec("DELETE FROM log_filters") db.MustExec("DELETE FROM log_filters")
db.MustExec("DELETE FROM logs") db.MustExec("DELETE FROM logs")
db.MustExec("DELETE FROM maker.pit_file_ilk")
db.MustExec("DELETE FROM maker.pit_file_stability_fee")
db.MustExec("DELETE FROM receipts") db.MustExec("DELETE FROM receipts")
db.MustExec("DELETE FROM transactions") db.MustExec("DELETE FROM transactions")
db.MustExec("DELETE FROM watched_contracts") db.MustExec("DELETE FROM watched_contracts")