From cb141f7cb70f5cd1f3e08fe0da80b8b7f5bbf7bd Mon Sep 17 00:00:00 2001 From: Rob Mulholand Date: Tue, 6 Nov 2018 11:11:09 -0600 Subject: [PATCH] (VDB-204) Add transformer for Flap kick --- cmd/continuousLogSync.go | 1 + .../1541525500_create_flap_kick.down.sql | 3 + .../1541525500_create_flap_kick.up.sql | 16 +++ db/schema.sql | 74 +++++++++++++- environments/local.toml.example | 1 + environments/public.toml.example | 1 + environments/staging.toml | 1 + pkg/transformers/flap_kick/config.go | 26 +++++ pkg/transformers/flap_kick/converter.go | 89 +++++++++++++++++ pkg/transformers/flap_kick/converter_test.go | 96 ++++++++++++++++++ pkg/transformers/flap_kick/entity.go | 33 +++++++ .../flap_kick/flap_kick_suite_test.go | 33 +++++++ pkg/transformers/flap_kick/model.go | 28 ++++++ pkg/transformers/flap_kick/repository.go | 91 +++++++++++++++++ pkg/transformers/flap_kick/repository_test.go | 98 +++++++++++++++++++ .../integration_tests/flap_kick.go | 68 +++++++++++++ pkg/transformers/shared/constants.go | 5 + .../shared/event_signature_generator_test.go | 14 +++ pkg/transformers/test_data/flap_kick.go | 50 ++++++++++ pkg/transformers/transformers.go | 9 ++ test_config/test_config.go | 1 + 21 files changed, 736 insertions(+), 2 deletions(-) create mode 100644 db/migrations/1541525500_create_flap_kick.down.sql create mode 100644 db/migrations/1541525500_create_flap_kick.up.sql create mode 100644 pkg/transformers/flap_kick/config.go create mode 100644 pkg/transformers/flap_kick/converter.go create mode 100644 pkg/transformers/flap_kick/converter_test.go create mode 100644 pkg/transformers/flap_kick/entity.go create mode 100644 pkg/transformers/flap_kick/flap_kick_suite_test.go create mode 100644 pkg/transformers/flap_kick/model.go create mode 100644 pkg/transformers/flap_kick/repository.go create mode 100644 pkg/transformers/flap_kick/repository_test.go create mode 100644 pkg/transformers/integration_tests/flap_kick.go create mode 100644 pkg/transformers/test_data/flap_kick.go diff --git a/cmd/continuousLogSync.go b/cmd/continuousLogSync.go index 859a720b..ae1ff82a 100644 --- a/cmd/continuousLogSync.go +++ b/cmd/continuousLogSync.go @@ -96,6 +96,7 @@ func buildTransformerInitializerMap() map[string]shared2.TransformerInitializer transformerInitializerMap[shared2.DripFileIlkLabel] = transformers.DripFileIlkTransformerInitializer transformerInitializerMap[shared2.DripFileRepoLabel] = transformers.DripFileRepoTransformerInitializer transformerInitializerMap[shared2.DripFileVowLabel] = transformers.DripFileVowTransfromerInitializer + transformerInitializerMap[shared2.FlapKickLabel] = transformers.FlapKickTransformerInitializer transformerInitializerMap[shared2.FlipKickLabel] = transformers.FlipKickTransformerInitializer transformerInitializerMap[shared2.VowFlogLabel] = transformers.FlogTransformerInitializer transformerInitializerMap[shared2.FlopKickLabel] = transformers.FlopKickTransformerInitializer diff --git a/db/migrations/1541525500_create_flap_kick.down.sql b/db/migrations/1541525500_create_flap_kick.down.sql new file mode 100644 index 00000000..48d4b5c1 --- /dev/null +++ b/db/migrations/1541525500_create_flap_kick.down.sql @@ -0,0 +1,3 @@ +DROP TABLE maker.flap_kick; +ALTER TABLE public.checked_headers + DROP COLUMN flap_kick_checked; \ No newline at end of file diff --git a/db/migrations/1541525500_create_flap_kick.up.sql b/db/migrations/1541525500_create_flap_kick.up.sql new file mode 100644 index 00000000..aabc8ec3 --- /dev/null +++ b/db/migrations/1541525500_create_flap_kick.up.sql @@ -0,0 +1,16 @@ +CREATE TABLE maker.flap_kick ( + id SERIAL PRIMARY KEY, + header_id INTEGER NOT NULL REFERENCES headers (id) ON DELETE CASCADE, + bid_id NUMERIC NOT NULL, + lot NUMERIC NOT NULL, + bid NUMERIC NOT NULL, + gal TEXT, + "end" TIMESTAMP WITH TIME ZONE, + tx_idx INTEGER NOT NULL, + log_idx INTEGER NOT NULL, + raw_log JSONB, + UNIQUE (header_id, tx_idx, log_idx) +); + +ALTER TABLE public.checked_headers + ADD COLUMN flap_kick_checked BOOLEAN NOT NULL DEFAULT FALSE; \ No newline at end of file diff --git a/db/schema.sql b/db/schema.sql index 5efd2671..faab8258 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -2,7 +2,7 @@ -- PostgreSQL database dump -- --- Dumped from database version 10.5 +-- Dumped from database version 10.3 -- Dumped by pg_dump version 10.5 SET statement_timeout = 0; @@ -417,6 +417,44 @@ CREATE SEQUENCE maker.drip_file_vow_id_seq ALTER SEQUENCE maker.drip_file_vow_id_seq OWNED BY maker.drip_file_vow.id; +-- +-- Name: flap_kick; Type: TABLE; Schema: maker; Owner: - +-- + +CREATE TABLE maker.flap_kick ( + id integer NOT NULL, + header_id integer NOT NULL, + bid_id numeric NOT NULL, + lot numeric NOT NULL, + bid numeric NOT NULL, + gal text, + "end" timestamp with time zone, + tx_idx integer NOT NULL, + log_idx integer NOT NULL, + raw_log jsonb +); + + +-- +-- Name: flap_kick_id_seq; Type: SEQUENCE; Schema: maker; Owner: - +-- + +CREATE SEQUENCE maker.flap_kick_id_seq + AS integer + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: flap_kick_id_seq; Type: SEQUENCE OWNED BY; Schema: maker; Owner: - +-- + +ALTER SEQUENCE maker.flap_kick_id_seq OWNED BY maker.flap_kick.id; + + -- -- Name: flip_kick; Type: TABLE; Schema: maker; Owner: - -- @@ -1187,7 +1225,8 @@ CREATE TABLE public.checked_headers ( vat_grab_checked boolean DEFAULT false NOT NULL, vat_flux_checked boolean DEFAULT false NOT NULL, vat_slip_checked boolean DEFAULT false NOT NULL, - vow_flog_checked boolean DEFAULT false NOT NULL + vow_flog_checked boolean DEFAULT false NOT NULL, + flap_kick_checked boolean DEFAULT false NOT NULL ); @@ -1579,6 +1618,13 @@ ALTER TABLE ONLY maker.drip_file_repo ALTER COLUMN id SET DEFAULT nextval('maker ALTER TABLE ONLY maker.drip_file_vow ALTER COLUMN id SET DEFAULT nextval('maker.drip_file_vow_id_seq'::regclass); +-- +-- Name: flap_kick id; Type: DEFAULT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.flap_kick ALTER COLUMN id SET DEFAULT nextval('maker.flap_kick_id_seq'::regclass); + + -- -- Name: flip_kick id; Type: DEFAULT; Schema: maker; Owner: - -- @@ -1935,6 +1981,22 @@ ALTER TABLE ONLY maker.drip_file_vow ADD CONSTRAINT drip_file_vow_pkey PRIMARY KEY (id); +-- +-- Name: flap_kick flap_kick_header_id_tx_idx_log_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.flap_kick + ADD CONSTRAINT flap_kick_header_id_tx_idx_log_idx_key UNIQUE (header_id, tx_idx, log_idx); + + +-- +-- Name: flap_kick flap_kick_pkey; Type: CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.flap_kick + ADD CONSTRAINT flap_kick_pkey PRIMARY KEY (id); + + -- -- Name: flip_kick flip_kick_header_id_tx_idx_log_idx_key; Type: CONSTRAINT; Schema: maker; Owner: - -- @@ -2457,6 +2519,14 @@ ALTER TABLE ONLY maker.drip_file_vow ADD CONSTRAINT drip_file_vow_header_id_fkey FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE; +-- +-- Name: flap_kick flap_kick_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: - +-- + +ALTER TABLE ONLY maker.flap_kick + ADD CONSTRAINT flap_kick_header_id_fkey FOREIGN KEY (header_id) REFERENCES public.headers(id) ON DELETE CASCADE; + + -- -- Name: flip_kick flip_kick_header_id_fkey; Type: FK CONSTRAINT; Schema: maker; Owner: - -- diff --git a/environments/local.toml.example b/environments/local.toml.example index 0d75c769..9a10ff99 100644 --- a/environments/local.toml.example +++ b/environments/local.toml.example @@ -10,6 +10,7 @@ ipcPath = "http://127.0.0.1:7545" cat = "0x2f34f22a00ee4b7a8f8bbc4eaee1658774c624e0" drip = "0x891c04639a5edcae088e546fa125b5d7fb6a2b9d" eth_flip = "0x32D496Ad866D110060866B7125981C73642cc509" +mcd_flap = "0x8868BAd8e74FcA4505676D1B5B21EcC23328d132" mcd_flop = "0x6191C9b0086c2eBF92300cC507009b53996FbFFa" pep = "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975" pip = "0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc" diff --git a/environments/public.toml.example b/environments/public.toml.example index ad6af0ee..dc294923 100644 --- a/environments/public.toml.example +++ b/environments/public.toml.example @@ -11,6 +11,7 @@ levelDbPath = cat = "0x2f34f22a00ee4b7a8f8bbc4eaee1658774c624e0" drip = "0x891c04639a5edcae088e546fa125b5d7fb6a2b9d" eth_flip = "0x32D496Ad866D110060866B7125981C73642cc509" +mcd_flap = "0x8868BAd8e74FcA4505676D1B5B21EcC23328d132" mcd_flop = "0x6191C9b0086c2eBF92300cC507009b53996FbFFa" pep = "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975" pip = "0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc" diff --git a/environments/staging.toml b/environments/staging.toml index 318cf7b2..5c81eb25 100644 --- a/environments/staging.toml +++ b/environments/staging.toml @@ -15,6 +15,7 @@ name = "maker_vdb_staging" cat = "0x2f34f22a00ee4b7a8f8bbc4eaee1658774c624e0" drip = "0x891c04639a5edcae088e546fa125b5d7fb6a2b9d" eth_flip = "0x32D496Ad866D110060866B7125981C73642cc509" +mcd_flap = "0x8868BAd8e74FcA4505676D1B5B21EcC23328d132" mcd_flop = "0x6191C9b0086c2eBF92300cC507009b53996FbFFa" pep = "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975" pip = "0x9FfFE440258B79c5d6604001674A4722FfC0f7Bc" diff --git a/pkg/transformers/flap_kick/config.go b/pkg/transformers/flap_kick/config.go new file mode 100644 index 00000000..32ac1cf2 --- /dev/null +++ b/pkg/transformers/flap_kick/config.go @@ -0,0 +1,26 @@ +// Copyright 2018 Vulcanize +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package flap_kick + +import "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + +var FlapKickConfig = shared.SingleTransformerConfig{ + TransformerName: shared.FlapKickLabel, + ContractAddresses: []string{shared.FlapperContractAddress}, + ContractAbi: shared.FlapperABI, + Topic: shared.FlapKickSignature, + StartingBlockNumber: 0, + EndingBlockNumber: 10000000, +} diff --git a/pkg/transformers/flap_kick/converter.go b/pkg/transformers/flap_kick/converter.go new file mode 100644 index 00000000..d5d74865 --- /dev/null +++ b/pkg/transformers/flap_kick/converter.go @@ -0,0 +1,89 @@ +// 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 flap_kick + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/vulcanize/vulcanizedb/pkg/geth" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "time" +) + +type FlapKickConverter struct { +} + +func (FlapKickConverter) ToEntities(contractAbi string, ethLogs []types.Log) ([]interface{}, error) { + var entities []interface{} + for _, ethLog := range ethLogs { + entity := &FlapKickEntity{} + address := ethLog.Address + abi, err := geth.ParseAbi(contractAbi) + if err != nil { + return nil, err + } + contract := bind.NewBoundContract(address, abi, nil, nil, nil) + err = contract.UnpackLog(entity, "Kick", ethLog) + if err != nil { + return nil, err + } + entity.Raw = ethLog + entity.TransactionIndex = ethLog.TxIndex + entity.LogIndex = ethLog.Index + entities = append(entities, *entity) + } + return entities, nil +} + +func (FlapKickConverter) ToModels(entities []interface{}) ([]interface{}, error) { + var models []interface{} + for _, entity := range entities { + flapKickEntity, ok := entity.(FlapKickEntity) + if !ok { + return nil, fmt.Errorf("entity of type %T, not %T", entity, FlapKickEntity{}) + } + + if flapKickEntity.Id == nil { + return nil, errors.New("FlapKick log ID cannot be nil.") + } + + id := flapKickEntity.Id.String() + lot := shared.BigIntToString(flapKickEntity.Lot) + bid := shared.BigIntToString(flapKickEntity.Bid) + gal := flapKickEntity.Gal.String() + endValue := shared.BigIntToInt64(flapKickEntity.End) + end := time.Unix(endValue, 0) + rawLog, err := json.Marshal(flapKickEntity.Raw) + if err != nil { + return nil, err + } + + model := FlapKickModel{ + BidId: id, + Lot: lot, + Bid: bid, + Gal: gal, + End: end, + TransactionIndex: flapKickEntity.TransactionIndex, + LogIndex: flapKickEntity.LogIndex, + Raw: rawLog, + } + models = append(models, model) + } + return models, nil +} diff --git a/pkg/transformers/flap_kick/converter_test.go b/pkg/transformers/flap_kick/converter_test.go new file mode 100644 index 00000000..617d98a9 --- /dev/null +++ b/pkg/transformers/flap_kick/converter_test.go @@ -0,0 +1,96 @@ +// 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 flap_kick_test + +import ( + "encoding/json" + "github.com/ethereum/go-ethereum/core/types" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/vulcanize/vulcanizedb/pkg/transformers/flap_kick" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + "math/big" + "time" +) + +var _ = Describe("Flap kick converter", func() { + var converter = flap_kick.FlapKickConverter{} + + Describe("ToEntity", func() { + It("converts an Eth Log to a FlapKickEntity", func() { + entities, err := converter.ToEntities(shared.FlapperABI, []types.Log{test_data.EthFlapKickLog}) + + Expect(err).NotTo(HaveOccurred()) + Expect(len(entities)).To(Equal(1)) + Expect(entities[0]).To(Equal(test_data.FlapKickEntity)) + }) + + It("returns an error if converting log to entity fails", func() { + _, err := converter.ToEntities("error abi", []types.Log{test_data.EthFlapKickLog}) + + Expect(err).To(HaveOccurred()) + }) + }) + + Describe("ToModel", func() { + + BeforeEach(func() { + }) + + It("converts an Entity to a Model", func() { + models, err := converter.ToModels([]interface{}{test_data.FlapKickEntity}) + + Expect(err).NotTo(HaveOccurred()) + Expect(len(models)).To(Equal(1)) + Expect(models[0]).To(Equal(test_data.FlapKickModel)) + }) + + It("handles nil values", func() { + emptyAddressHex := "0x0000000000000000000000000000000000000000" + emptyString := "" + emptyTime := time.Unix(0, 0) + emptyEntity := flap_kick.FlapKickEntity{} + emptyEntity.Id = big.NewInt(1) + emptyRawLogJson, err := json.Marshal(types.Log{}) + Expect(err).NotTo(HaveOccurred()) + + models, err := converter.ToModels([]interface{}{emptyEntity}) + + Expect(err).NotTo(HaveOccurred()) + Expect(len(models)).To(Equal(1)) + model := models[0].(flap_kick.FlapKickModel) + Expect(model.BidId).To(Equal("1")) + Expect(model.Lot).To(Equal(emptyString)) + Expect(model.Bid).To(Equal(emptyString)) + Expect(model.Gal).To(Equal(emptyAddressHex)) + Expect(model.End).To(Equal(emptyTime)) + Expect(model.Raw).To(Equal(emptyRawLogJson)) + }) + + It("returns an error if the flap kick event id is nil", func() { + _, err := converter.ToModels([]interface{}{flap_kick.FlapKickEntity{}}) + + Expect(err).To(HaveOccurred()) + }) + + It("returns an error if the wrong entity type is passed in", func() { + _, err := converter.ToModels([]interface{}{test_data.WrongEntity{}}) + + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("entity of type")) + }) + }) +}) diff --git a/pkg/transformers/flap_kick/entity.go b/pkg/transformers/flap_kick/entity.go new file mode 100644 index 00000000..fd95bcb2 --- /dev/null +++ b/pkg/transformers/flap_kick/entity.go @@ -0,0 +1,33 @@ +// 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 flap_kick + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +type FlapKickEntity struct { + Id *big.Int + Lot *big.Int + Bid *big.Int + Gal common.Address + End *big.Int + Raw types.Log + TransactionIndex uint + LogIndex uint +} diff --git a/pkg/transformers/flap_kick/flap_kick_suite_test.go b/pkg/transformers/flap_kick/flap_kick_suite_test.go new file mode 100644 index 00000000..9baa4235 --- /dev/null +++ b/pkg/transformers/flap_kick/flap_kick_suite_test.go @@ -0,0 +1,33 @@ +// 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 flap_kick_test + +import ( + "io/ioutil" + "log" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestFlapKick(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "FlapKick Suite") +} + +var _ = BeforeSuite(func() { + log.SetOutput(ioutil.Discard) +}) diff --git a/pkg/transformers/flap_kick/model.go b/pkg/transformers/flap_kick/model.go new file mode 100644 index 00000000..b50c8404 --- /dev/null +++ b/pkg/transformers/flap_kick/model.go @@ -0,0 +1,28 @@ +// Copyright 2018 Vulcanize +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package flap_kick + +import "time" + +type FlapKickModel struct { + BidId string `db:"bid_id"` + Lot string + Bid string + Gal string + End time.Time + LogIndex uint `db:"log_idx"` + TransactionIndex uint `db:"tx_idx"` + Raw []byte `db:"raw_log"` +} diff --git a/pkg/transformers/flap_kick/repository.go b/pkg/transformers/flap_kick/repository.go new file mode 100644 index 00000000..1d0c6e85 --- /dev/null +++ b/pkg/transformers/flap_kick/repository.go @@ -0,0 +1,91 @@ +// 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 flap_kick + +import ( + "fmt" + "github.com/vulcanize/vulcanizedb/pkg/core" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" +) + +type FlapKickRepository struct { + db *postgres.DB +} + +func (repository *FlapKickRepository) Create(headerID int64, models []interface{}) error { + tx, err := repository.db.Begin() + if err != nil { + return err + } + for _, model := range models { + flapKickModel, ok := model.(FlapKickModel) + if !ok { + return fmt.Errorf("model of type %T, not %T", model, FlapKickModel{}) + } + _, err := tx.Exec( + `INSERT into maker.flap_kick (header_id, bid_id, lot, bid, gal, "end", tx_idx, log_idx, raw_log) + VALUES($1, $2::NUMERIC, $3::NUMERIC, $4::NUMERIC, $5, $6, $7, $8, $9)`, + headerID, flapKickModel.BidId, flapKickModel.Lot, flapKickModel.Bid, flapKickModel.Gal, flapKickModel.End, flapKickModel.TransactionIndex, flapKickModel.LogIndex, flapKickModel.Raw, + ) + if err != nil { + tx.Rollback() + return err + } + } + _, err = tx.Exec(`INSERT INTO public.checked_headers (header_id, flap_kick_checked) + VALUES ($1, $2) + ON CONFLICT (header_id) DO + UPDATE SET flap_kick_checked = $2`, headerID, true) + if err != nil { + tx.Rollback() + return err + } + return tx.Commit() +} + +func (repository *FlapKickRepository) MarkHeaderChecked(headerID int64) error { + _, err := repository.db.Exec(`INSERT INTO public.checked_headers (header_id, flap_kick_checked) + VALUES ($1, $2) + ON CONFLICT (header_id) DO + UPDATE SET flap_kick_checked = $2`, headerID, true) + return err +} + +func (repository FlapKickRepository) 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 checked_headers on headers.id = header_id + WHERE (header_id ISNULL OR flap_kick_checked IS FALSE) + AND headers.block_number >= $1 + AND headers.block_number <= $2 + AND headers.eth_node_fingerprint = $3`, + startingBlockNumber, + endingBlockNumber, + repository.db.Node.ID, + ) + + if err != nil { + fmt.Println("Error:", err) + return result, err + } + + return result, nil +} + +func (repository *FlapKickRepository) SetDB(db *postgres.DB) { + repository.db = db +} diff --git a/pkg/transformers/flap_kick/repository_test.go b/pkg/transformers/flap_kick/repository_test.go new file mode 100644 index 00000000..08ae63b9 --- /dev/null +++ b/pkg/transformers/flap_kick/repository_test.go @@ -0,0 +1,98 @@ +// 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 flap_kick_test + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres" + "github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories" + "github.com/vulcanize/vulcanizedb/pkg/fakes" + "github.com/vulcanize/vulcanizedb/pkg/transformers/flap_kick" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data" + "github.com/vulcanize/vulcanizedb/pkg/transformers/test_data/shared_behaviors" + "github.com/vulcanize/vulcanizedb/test_config" +) + +var _ = Describe("Flap Kick Repository", func() { + var ( + db *postgres.DB + flapKickRepository flap_kick.FlapKickRepository + headerRepository repositories.HeaderRepository + ) + + BeforeEach(func() { + db = test_config.NewTestDB(test_config.NewTestNode()) + test_config.CleanTestDB(db) + flapKickRepository = flap_kick.FlapKickRepository{} + flapKickRepository.SetDB(db) + headerRepository = repositories.NewHeaderRepository(db) + }) + + Describe("Create", func() { + modelWithDifferentLogIdx := test_data.FlapKickModel + modelWithDifferentLogIdx.LogIndex = modelWithDifferentLogIdx.LogIndex + 1 + inputs := shared_behaviors.CreateBehaviorInputs{ + CheckedHeaderColumnName: "flap_kick_checked", + LogEventTableName: "maker.flap_kick", + TestModel: test_data.FlapKickModel, + ModelWithDifferentLogIdx: modelWithDifferentLogIdx, + Repository: &flapKickRepository, + } + + shared_behaviors.SharedRepositoryCreateBehaviors(&inputs) + + It("persists a flap kick record", func() { + headerId, err := headerRepository.CreateOrUpdateHeader(fakes.FakeHeader) + Expect(err).NotTo(HaveOccurred()) + err = flapKickRepository.Create(headerId, []interface{}{test_data.FlapKickModel}) + + Expect(err).NotTo(HaveOccurred()) + var count int + db.QueryRow(`SELECT count(*) FROM maker.flap_kick`).Scan(&count) + Expect(count).To(Equal(1)) + var dbResult flap_kick.FlapKickModel + err = db.Get(&dbResult, `SELECT bid, bid_id, "end", gal, lot, log_idx, tx_idx, raw_log FROM maker.flap_kick WHERE header_id = $1`, headerId) + Expect(err).NotTo(HaveOccurred()) + Expect(dbResult.Bid).To(Equal(test_data.FlapKickModel.Bid)) + Expect(dbResult.BidId).To(Equal(test_data.FlapKickModel.BidId)) + Expect(dbResult.End.Equal(test_data.FlapKickModel.End)).To(BeTrue()) + Expect(dbResult.Gal).To(Equal(test_data.FlapKickModel.Gal)) + Expect(dbResult.Lot).To(Equal(test_data.FlapKickModel.Lot)) + Expect(dbResult.LogIndex).To(Equal(test_data.FlapKickModel.LogIndex)) + Expect(dbResult.TransactionIndex).To(Equal(test_data.FlapKickModel.TransactionIndex)) + Expect(dbResult.Raw).To(MatchJSON(test_data.FlapKickModel.Raw)) + }) + }) + + Describe("MarkHeaderChecked", func() { + inputs := shared_behaviors.MarkedHeaderCheckedBehaviorInputs{ + CheckedHeaderColumnName: "flap_kick_checked", + Repository: &flapKickRepository, + } + + shared_behaviors.SharedRepositoryMarkHeaderCheckedBehaviors(&inputs) + }) + + Describe("MissingHeaders", func() { + inputs := shared_behaviors.MissingHeadersBehaviorInputs{ + Repository: &flapKickRepository, + RepositoryTwo: &flap_kick.FlapKickRepository{}, + } + + shared_behaviors.SharedRepositoryMissingHeadersBehaviors(&inputs) + }) +}) diff --git a/pkg/transformers/integration_tests/flap_kick.go b/pkg/transformers/integration_tests/flap_kick.go new file mode 100644 index 00000000..7bf6d82f --- /dev/null +++ b/pkg/transformers/integration_tests/flap_kick.go @@ -0,0 +1,68 @@ +// 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 integration_tests + +import ( + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/flap_kick" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "github.com/vulcanize/vulcanizedb/test_config" +) + +var _ = Describe("FlapKick Transformer", func() { + It("fetches and transforms a FlapKick event from Kovan chain", func() { + blockNumber := int64(9002933) + config := flap_kick.FlapKickConfig + config.StartingBlockNumber = blockNumber + config.EndingBlockNumber = blockNumber + + rpcClient, ethClient, err := getClients(ipc) + Expect(err).NotTo(HaveOccurred()) + blockchain, err := getBlockChain(rpcClient, ethClient) + Expect(err).NotTo(HaveOccurred()) + + db := test_config.NewTestDB(blockchain.Node()) + test_config.CleanTestDB(db) + + err = persistHeader(db, blockNumber) + Expect(err).NotTo(HaveOccurred()) + + initializer := factories.Transformer{ + Config: flap_kick.FlapKickConfig, + Converter: &flap_kick.FlapKickConverter{}, + Repository: &flap_kick.FlapKickRepository{}, + Fetcher: &shared.Fetcher{}, + } + transformer := initializer.NewTransformer(db, blockchain) + err = transformer.Execute() + Expect(err).NotTo(HaveOccurred()) + + var dbResult []flap_kick.FlapKickModel + err = db.Select(&dbResult, `SELECT bid, bid_id, "end", gal, lot FROM maker.flap_kick`) + Expect(err).NotTo(HaveOccurred()) + + Expect(len(dbResult)).To(Equal(1)) + Expect(dbResult[0].Bid).To(Equal("0")) + Expect(dbResult[0].BidId).To(Equal("1")) + Expect(dbResult[0].End.Equal(time.Unix(1539163860, 0))).To(BeTrue()) + Expect(dbResult[0].Gal).To(Equal("0x0000d8b4147eDa80Fec7122AE16DA2479Cbd7ffB")) + Expect(dbResult[0].Lot).To(Equal("1000000000000000000")) + }) +}) diff --git a/pkg/transformers/shared/constants.go b/pkg/transformers/shared/constants.go index 281c1107..998dc551 100644 --- a/pkg/transformers/shared/constants.go +++ b/pkg/transformers/shared/constants.go @@ -31,6 +31,7 @@ var ( CatABI = `[{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x36569e77"},{"constant":true,"inputs":[],"name":"vow","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x626cb3c5"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"flips","outputs":[{"name":"ilk","type":"bytes32"},{"name":"urn","type":"bytes32"},{"name":"ink","type":"uint256"},{"name":"tab","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x70d9235a"},{"constant":true,"inputs":[],"name":"nflip","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x76181a51"},{"constant":true,"inputs":[],"name":"live","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x957aa58c"},{"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":"flip","type":"address"},{"name":"chop","type":"uint256"},{"name":"lump","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd9638d36"},{"constant":true,"inputs":[],"name":"pit","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xf03c7c6e"},{"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":"tab","type":"uint256"},{"indexed":false,"name":"flip","type":"uint256"},{"indexed":false,"name":"iArt","type":"uint256"}],"name":"Bite","type":"event","signature":"0x99b5620489b6ef926d4518936cfec15d305452712b88bd59da2d9c10fb0953e8"},{"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":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xd4e8be83"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"what","type":"bytes32"},{"name":"flip","type":"address"}],"name":"file","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xebecb39d"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"urn","type":"bytes32"}],"name":"bite","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x72f7b593"},{"constant":false,"inputs":[{"name":"n","type":"uint256"},{"name":"wad","type":"uint256"}],"name":"flip","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xe6f95917"}]` DripABI = `[{"constant":true,"inputs":[],"name":"vat","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x36569e77"},{"constant":true,"inputs":[],"name":"repo","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x56ff3122"},{"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":"vow","type":"bytes32"},{"name":"tax","type":"uint256"},{"name":"rho","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd9638d36"},{"inputs":[{"name":"vat_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"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":true,"inputs":[],"name":"era","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x143e55e0"},{"constant":false,"inputs":[{"name":"ilk","type":"bytes32"},{"name":"vow","type":"bytes32"},{"name":"tax","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":"ilk","type":"bytes32"}],"name":"drip","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x44e2a5a8"}]` + FlapperABI = `[{"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":"gal","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ttl","outputs":[{"name":"","type":"uint48"}],"payable":false,"stateMutability":"view","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":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":true,"inputs":[],"name":"dai","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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"}],"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"},{"constant":false,"inputs":[{"name":"gal","type":"address"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"kick","outputs":[{"name":"id","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","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":false,"inputs":[{"name":"id","type":"uint256"}],"name":"deal","outputs":[],"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"}]` FlopperABI = `[{"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":"vow","type":"address"}],"payable":false,"stateMutability":"view","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":false,"inputs":[{"name":"guy","type":"address"}],"name":"rely","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":"guy","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"gal","type":"address"},{"name":"lot","type":"uint256"},{"name":"bid","type":"uint256"}],"name":"kick","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"wards","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":true,"inputs":[],"name":"dai","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","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"}],"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"}]` 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"}]]` @@ -41,6 +42,7 @@ var ( // temporary addresses from Kovan deployment CatContractAddress = getContractValue("contract.cat", "0x2f34f22a00ee4b7a8f8bbc4eaee1658774c624e0") DripContractAddress = getContractValue("contract.drip", "0x891c04639a5edcae088e546fa125b5d7fb6a2b9d") + FlapperContractAddress = getContractValue("contract.mcd_flap", "0x8868BAd8e74FcA4505676D1B5B21EcC23328d132") // MCD FLAP Contract FlipperContractAddress = getContractValue("contract.eth_flip", "0x32D496Ad866D110060866B7125981C73642cc509") // ETH FLIP Contract FlopperContractAddress = getContractValue("contract.mcd_flop", "0x6191C9b0086c2eBF92300cC507009b53996FbFFa") // MCD FLOP Contract PepContractAddress = getContractValue("contract.pep", "0xB1997239Cfc3d15578A3a09730f7f84A90BB4975") @@ -61,6 +63,7 @@ var ( dripFileIlkMethod = "file(bytes32,bytes32,uint256)" dripFileRepoMethod = GetSolidityMethodSignature(DripABI, "file") dripFileVowMethod = "file(bytes32,bytes32)" + flapKickMethod = GetSolidityMethodSignature(FlapperABI, "Kick") flipKickMethod = GetSolidityMethodSignature(FlipperABI, "Kick") flopKickMethod = GetSolidityMethodSignature(FlopperABI, "Kick") frobMethod = GetSolidityMethodSignature(PitABI, "Frob") @@ -90,6 +93,7 @@ var ( DripFileIlkSignature = GetLogNoteSignature(dripFileIlkMethod) DripFileRepoSignature = GetLogNoteSignature(dripFileRepoMethod) DripFileVowSignature = GetLogNoteSignature(dripFileVowMethod) + FlapKickSignature = GetEventSignature(flapKickMethod) FlipKickSignature = GetEventSignature(flipKickMethod) FlopKickSignature = GetEventSignature(flopKickMethod) FrobSignature = GetEventSignature(frobMethod) @@ -119,6 +123,7 @@ var ( DripFileIlkLabel = "dripFileIlk" DripFileRepoLabel = "dripFileRepo" DripFileVowLabel = "dripFileVow" + FlapKickLabel = "flapKick" FlipKickLabel = "flipKick" FlopKickLabel = "flopKick" FrobLabel = "frob" diff --git a/pkg/transformers/shared/event_signature_generator_test.go b/pkg/transformers/shared/event_signature_generator_test.go index 21a1ead1..ca93b39c 100644 --- a/pkg/transformers/shared/event_signature_generator_test.go +++ b/pkg/transformers/shared/event_signature_generator_test.go @@ -37,6 +37,13 @@ var _ = Describe("Event signature generator", func() { Expect(expected).To(Equal(actual)) }) + It("generates the flap kick event signature", func() { + expected := "0xefa52d9342a199cb30efd2692463f2c2bef63cd7186b50382d4fb94ad207880e" + actual := shared.GetEventSignature("Kick(uint256,uint256,uint256,address,uint48)") + + 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)") @@ -224,6 +231,13 @@ var _ = Describe("Event signature generator", func() { Expect(expected).To(Equal(actual)) }) + It("gets the flap Kick event signature", func() { + expected := "Kick(uint256,uint256,uint256,address,uint48)" + actual := shared.GetSolidityMethodSignature(shared.FlapperABI, "Kick") + + Expect(expected).To(Equal(actual)) + }) + It("gets the flip Kick event signature", func() { expected := "Kick(uint256,uint256,uint256,address,uint48,bytes32,uint256)" actual := shared.GetSolidityMethodSignature(shared.FlipperABI, "Kick") diff --git a/pkg/transformers/test_data/flap_kick.go b/pkg/transformers/test_data/flap_kick.go new file mode 100644 index 00000000..eecd5f92 --- /dev/null +++ b/pkg/transformers/test_data/flap_kick.go @@ -0,0 +1,50 @@ +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/flap_kick" + "github.com/vulcanize/vulcanizedb/pkg/transformers/shared" + "math/big" + "time" +) + +var EthFlapKickLog = types.Log{ + Address: common.HexToAddress(shared.FlapperContractAddress), + Topics: []common.Hash{ + common.HexToHash("0xefa52d9342a199cb30efd2692463f2c2bef63cd7186b50382d4fb94ad207880e"), + common.HexToHash("0x00000000000000000000000000000000000000000000000000000000069f6bc7"), + }, + Data: hexutil.MustDecode("0x000000000000000000000000000000000000000000000000000000003ade68b100000000000000000000000000000000000000000000000000000000075bcd150000000000000000000000007d7bee5fcfd8028cf7b00876c5b1421c800561a6000000000000000000000000000000000000000000000000000000005be469c5"), + BlockNumber: 65, + TxHash: common.HexToHash("0xee7930b76b6e93974bd3f37824644ae42a89a3887a1131a7bcb3267ab4dc0169"), + TxIndex: 66, + BlockHash: common.HexToHash("0x051525dfb9a524739ae09ec240ecd5ddbc172ccdc2f65670786fa9f37806c378"), + Index: 67, + Removed: false, +} + +var FlapKickEntity = flap_kick.FlapKickEntity{ + Id: big.NewInt(111111111), + Lot: big.NewInt(987654321), + Bid: big.NewInt(123456789), + Gal: common.HexToAddress("0x7d7bEe5fCfD8028cf7b00876C5b1421c800561A6"), + End: big.NewInt(1541695941), + Raw: EthFlapKickLog, + TransactionIndex: EthFlapKickLog.TxIndex, + LogIndex: EthFlapKickLog.Index, +} + +var rawFlapKickLog, _ = json.Marshal(EthFlapKickLog) +var FlapKickModel = flap_kick.FlapKickModel{ + BidId: FlapKickEntity.Id.String(), + Lot: FlapKickEntity.Lot.String(), + Bid: FlapKickEntity.Bid.String(), + Gal: FlapKickEntity.Gal.String(), + End: time.Unix(1541695941, 0), + Raw: rawFlapKickLog, + TransactionIndex: EthFlapKickLog.TxIndex, + LogIndex: EthFlapKickLog.Index, +} diff --git a/pkg/transformers/transformers.go b/pkg/transformers/transformers.go index 9cd6a48e..b4a7c210 100644 --- a/pkg/transformers/transformers.go +++ b/pkg/transformers/transformers.go @@ -26,6 +26,7 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/repo" "github.com/vulcanize/vulcanizedb/pkg/transformers/drip_file/vow" "github.com/vulcanize/vulcanizedb/pkg/transformers/factories" + "github.com/vulcanize/vulcanizedb/pkg/transformers/flap_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/flop_kick" "github.com/vulcanize/vulcanizedb/pkg/transformers/frob" @@ -118,6 +119,13 @@ var ( Fetcher: &shared.Fetcher{}, }.NewLogNoteTransformer + FlapKickTransformerInitializer = factories.Transformer{ + Config: flap_kick.FlapKickConfig, + Converter: &flap_kick.FlapKickConverter{}, + Repository: &flap_kick.FlapKickRepository{}, + Fetcher: &shared.Fetcher{}, + }.NewTransformer + FlipKickTransformerInitializer = factories.Transformer{ Config: flip_kick.FlipKickConfig, Converter: &flip_kick.FlipKickConverter{}, @@ -257,6 +265,7 @@ func TransformerInitializers() []shared.TransformerInitializer { DripFileIlkTransformerInitializer, DripFileVowTransfromerInitializer, DripFileRepoTransformerInitializer, + FlapKickTransformerInitializer, FlipKickTransformerInitializer, FlogTransformerInitializer, FlopKickTransformerInitializer, diff --git a/test_config/test_config.go b/test_config/test_config.go index 12a81b63..cd070e07 100644 --- a/test_config/test_config.go +++ b/test_config/test_config.go @@ -88,6 +88,7 @@ func CleanTestDB(db *postgres.DB) { db.MustExec("DELETE FROM maker.drip_file_ilk") db.MustExec("DELETE FROM maker.drip_file_repo") db.MustExec("DELETE FROM maker.drip_file_vow") + db.MustExec("DELETE FROM maker.flap_kick") db.MustExec("DELETE FROM maker.flip_kick") db.MustExec("DELETE FROM maker.vow_flog") db.MustExec("DELETE FROM maker.flop_kick")