Changes to address Rob's comments. Added generic/event_triggered transformer, tests, and repo migrations for Burn and Mint events

This commit is contained in:
Ian Norden 2018-08-31 14:48:43 -05:00
parent 4aa403d90d
commit d66e50dad6
49 changed files with 1688 additions and 477 deletions

View File

@ -0,0 +1 @@
DROP TABLE token_burns;

View File

@ -0,0 +1,13 @@
CREATE TABLE token_burns (
id SERIAL,
vulcanize_log_id INTEGER NOT NULL UNIQUE,
token_name CHARACTER VARYING(66) NOT NULL,
token_address CHARACTER VARYING(66) NOT NULL,
burner CHARACTER VARYING(66) NOT NULL,
tokens DECIMAL NOT NULL,
block INTEGER NOT NULL,
tx CHARACTER VARYING(66) NOT NULL,
CONSTRAINT log_index_fk FOREIGN KEY (vulcanize_log_id)
REFERENCES logs (id)
ON DELETE CASCADE
)

View File

@ -0,0 +1 @@
DROP TABLE token_mints;

View File

@ -0,0 +1,14 @@
CREATE TABLE token_mints (
id SERIAL,
vulcanize_log_id INTEGER NOT NULL UNIQUE,
token_name CHARACTER VARYING(66) NOT NULL,
token_address CHARACTER VARYING(66) NOT NULL,
minter CHARACTER VARYING(66) NOT NULL,
mintee CHARACTER VARYING(66) NOT NULL,
tokens DECIMAL NOT NULL,
block INTEGER NOT NULL,
tx CHARACTER VARYING(66) NOT NULL,
CONSTRAINT log_index_fk FOREIGN KEY (vulcanize_log_id)
REFERENCES logs (id)
ON DELETE CASCADE
)

File diff suppressed because one or more lines are too long

View File

@ -17,9 +17,12 @@ package event_triggered
import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/examples/generic/helpers"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/geth"
)
// Converter converts a raw event log into its corresponding entity
@ -27,26 +30,35 @@ import (
type ERC20ConverterInterface interface {
ToTransferEntity(watchedEvent core.WatchedEvent) (*TransferEntity, error)
ToTransferModel(entity TransferEntity) TransferModel
ToTransferModel(entity *TransferEntity) *TransferModel
ToApprovalEntity(watchedEvent core.WatchedEvent) (*ApprovalEntity, error)
ToApprovalModel(entity ApprovalEntity) ApprovalModel
ToApprovalModel(entity *ApprovalEntity) *ApprovalModel
}
type ERC20Converter struct {
config generic.ContractConfig
}
func NewERC20Converter(config generic.ContractConfig) ERC20Converter {
return ERC20Converter{
func NewERC20Converter(config generic.ContractConfig) (*ERC20Converter, error) {
var err error
config.ParsedAbi, err = geth.ParseAbi(config.Abi)
if err != nil {
return nil, err
}
converter := &ERC20Converter{
config: config,
}
return converter, nil
}
func (c ERC20Converter) ToTransferEntity(watchedEvent core.WatchedEvent) (*TransferEntity, error) {
result := &TransferEntity{}
contract := bind.NewBoundContract(common.HexToAddress(c.config.Address), c.config.ParsedAbi, nil, nil, nil)
event := helpers.ConvertToLog(watchedEvent)
err := contract.UnpackLog(result, "Transfer", event)
err := contract.UnpackLog(result, constants.TransferEvent.String(), event)
if err != nil {
return result, err
}
@ -58,20 +70,19 @@ func (c ERC20Converter) ToTransferEntity(watchedEvent core.WatchedEvent) (*Trans
return result, nil
}
func (c ERC20Converter) ToTransferModel(transferEntity TransferEntity) TransferModel {
to := transferEntity.Dst.String()
from := transferEntity.Src.String()
tokens := transferEntity.Wad.String()
block := transferEntity.Block
tx := transferEntity.TxHash
return TransferModel{
func (c ERC20Converter) ToTransferModel(entity *TransferEntity) *TransferModel {
to := entity.Dst.String()
from := entity.Src.String()
tokens := entity.Wad.String()
return &TransferModel{
TokenName: c.config.Name,
TokenAddress: c.config.Address,
To: to,
From: from,
Tokens: tokens,
Block: block,
TxHash: tx,
Block: entity.Block,
TxHash: entity.TxHash,
}
}
@ -79,7 +90,7 @@ func (c ERC20Converter) ToApprovalEntity(watchedEvent core.WatchedEvent) (*Appro
result := &ApprovalEntity{}
contract := bind.NewBoundContract(common.HexToAddress(c.config.Address), c.config.ParsedAbi, nil, nil, nil)
event := helpers.ConvertToLog(watchedEvent)
err := contract.UnpackLog(result, "Approval", event)
err := contract.UnpackLog(result, constants.ApprovalEvent.String(), event)
if err != nil {
return result, err
}
@ -91,19 +102,18 @@ func (c ERC20Converter) ToApprovalEntity(watchedEvent core.WatchedEvent) (*Appro
return result, nil
}
func (c ERC20Converter) ToApprovalModel(TransferEntity ApprovalEntity) ApprovalModel {
tokenOwner := TransferEntity.Src.String()
spender := TransferEntity.Guy.String()
tokens := TransferEntity.Wad.String()
block := TransferEntity.Block
tx := TransferEntity.TxHash
return ApprovalModel{
func (c ERC20Converter) ToApprovalModel(entity *ApprovalEntity) *ApprovalModel {
tokenOwner := entity.Src.String()
spender := entity.Guy.String()
tokens := entity.Wad.String()
return &ApprovalModel{
TokenName: c.config.Name,
TokenAddress: c.config.Address,
Owner: tokenOwner,
Spender: spender,
Tokens: tokens,
Block: block,
TxHash: tx,
Block: entity.Block,
TxHash: entity.TxHash,
}
}

View File

@ -18,6 +18,7 @@ import (
"github.com/ethereum/go-ethereum/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/generic"
@ -27,7 +28,7 @@ import (
var expectedTransferModel = event_triggered.TransferModel{
TokenName: "Dai",
TokenAddress: "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359",
TokenAddress: constants.DaiContractAddress,
To: "0x09BbBBE21a5975cAc061D82f7b843bCE061BA391",
From: "0x000000000000000000000000000000000000Af21",
Tokens: "1097077688018008265106216665536940668749033598146",
@ -37,7 +38,7 @@ var expectedTransferModel = event_triggered.TransferModel{
var expectedTransferEntity = event_triggered.TransferEntity{
TokenName: "Dai",
TokenAddress: common.HexToAddress("0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"),
TokenAddress: common.HexToAddress(constants.DaiContractAddress),
Src: common.HexToAddress("0x000000000000000000000000000000000000Af21"),
Dst: common.HexToAddress("0x09BbBBE21a5975cAc061D82f7b843bCE061BA391"),
Wad: helpers.BigFromString("1097077688018008265106216665536940668749033598146"),
@ -47,7 +48,7 @@ var expectedTransferEntity = event_triggered.TransferEntity{
var expectedApprovalModel = event_triggered.ApprovalModel{
TokenName: "Dai",
TokenAddress: "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359",
TokenAddress: constants.DaiContractAddress,
Owner: "0x000000000000000000000000000000000000Af21",
Spender: "0x09BbBBE21a5975cAc061D82f7b843bCE061BA391",
Tokens: "1097077688018008265106216665536940668749033598146",
@ -57,7 +58,7 @@ var expectedApprovalModel = event_triggered.ApprovalModel{
var expectedApprovalEntity = event_triggered.ApprovalEntity{
TokenName: "Dai",
TokenAddress: common.HexToAddress("0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"),
TokenAddress: common.HexToAddress(constants.DaiContractAddress),
Src: common.HexToAddress("0x000000000000000000000000000000000000Af21"),
Guy: common.HexToAddress("0x09BbBBE21a5975cAc061D82f7b843bCE061BA391"),
Wad: helpers.BigFromString("1097077688018008265106216665536940668749033598146"),
@ -67,12 +68,12 @@ var expectedApprovalEntity = event_triggered.ApprovalEntity{
var transferEvent = core.WatchedEvent{
LogID: 1,
Name: "Transfer",
Name: constants.TransferEvent.String(),
BlockNumber: 5488076,
Address: constants.DaiContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.TransferEventSignature,
Topic0: constants.TransferEvent.Signature(),
Topic1: "0x000000000000000000000000000000000000000000000000000000000000af21",
Topic2: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic3: "",
@ -81,12 +82,12 @@ var transferEvent = core.WatchedEvent{
var approvalEvent = core.WatchedEvent{
LogID: 1,
Name: "Approval",
Name: constants.ApprovalEvent.String(),
BlockNumber: 5488076,
Address: constants.DaiContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.ApprovalEventSignature,
Topic0: constants.ApprovalEvent.Signature(),
Topic1: "0x000000000000000000000000000000000000000000000000000000000000af21",
Topic2: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic3: "",
@ -95,20 +96,19 @@ var approvalEvent = core.WatchedEvent{
var _ = Describe("Transfer Converter", func() {
daiConverter := event_triggered.NewERC20Converter(generic.DaiConfig)
var daiConverter *event_triggered.ERC20Converter
var err error
BeforeEach(func() {
daiConverter, err = event_triggered.NewERC20Converter(generic.DaiConfig)
Expect(err).NotTo(HaveOccurred())
})
It("converts a watched transfer event into a TransferEntity", func() {
result, err := daiConverter.ToTransferEntity(transferEvent)
Expect(err).NotTo(HaveOccurred())
Expect(result.TokenName).To(Equal(expectedTransferEntity.TokenName))
Expect(result.TokenAddress).To(Equal(expectedTransferEntity.TokenAddress))
Expect(result.Dst).To(Equal(expectedTransferEntity.Dst))
Expect(result.Src).To(Equal(expectedTransferEntity.Src))
Expect(result.Wad).To(Equal(expectedTransferEntity.Wad))
Expect(result.Block).To(Equal(expectedTransferEntity.Block))
Expect(result.TxHash).To(Equal(expectedTransferEntity.TxHash))
Expect(result).To(Equal(&expectedTransferEntity))
})
It("converts a TransferEntity to an TransferModel", func() {
@ -116,35 +116,27 @@ var _ = Describe("Transfer Converter", func() {
result, err := daiConverter.ToTransferEntity(transferEvent)
Expect(err).NotTo(HaveOccurred())
model := daiConverter.ToTransferModel(*result)
Expect(model.TokenName).To(Equal(expectedTransferModel.TokenName))
Expect(model.TokenAddress).To(Equal(expectedTransferModel.TokenAddress))
Expect(model.To).To(Equal(expectedTransferModel.To))
Expect(model.From).To(Equal(expectedTransferModel.From))
Expect(model.Tokens).To(Equal(expectedTransferModel.Tokens))
Expect(model.Block).To(Equal(expectedTransferModel.Block))
Expect(model.TxHash).To(Equal(expectedTransferModel.TxHash))
model := daiConverter.ToTransferModel(result)
Expect(model).To(Equal(&expectedTransferModel))
})
})
var _ = Describe("Approval Converter", func() {
daiConverter := event_triggered.NewERC20Converter(generic.DaiConfig)
var daiConverter *event_triggered.ERC20Converter
var err error
BeforeEach(func() {
daiConverter, err = event_triggered.NewERC20Converter(generic.DaiConfig)
Expect(err).NotTo(HaveOccurred())
})
It("converts a watched approval event into a ApprovalEntity", func() {
result, err := daiConverter.ToApprovalEntity(approvalEvent)
Expect(err).NotTo(HaveOccurred())
Expect(result.TokenName).To(Equal(expectedApprovalEntity.TokenName))
Expect(result.TokenAddress).To(Equal(expectedApprovalEntity.TokenAddress))
Expect(result.Src).To(Equal(expectedApprovalEntity.Src))
Expect(result.Guy).To(Equal(expectedApprovalEntity.Guy))
Expect(result.Wad).To(Equal(expectedApprovalEntity.Wad))
Expect(result.Block).To(Equal(expectedApprovalEntity.Block))
Expect(result.TxHash).To(Equal(expectedApprovalEntity.TxHash))
Expect(result).To(Equal(&expectedApprovalEntity))
})
It("converts a ApprovalEntity to an ApprovalModel", func() {
@ -152,15 +144,8 @@ var _ = Describe("Approval Converter", func() {
result, err := daiConverter.ToApprovalEntity(approvalEvent)
Expect(err).NotTo(HaveOccurred())
model := daiConverter.ToApprovalModel(*result)
Expect(model.TokenName).To(Equal(expectedApprovalModel.TokenName))
Expect(model.TokenAddress).To(Equal(expectedApprovalModel.TokenAddress))
Expect(model.Owner).To(Equal(expectedApprovalModel.Owner))
Expect(model.Spender).To(Equal(expectedApprovalModel.Spender))
Expect(model.Tokens).To(Equal(expectedApprovalModel.Tokens))
Expect(model.Block).To(Equal(expectedApprovalModel.Block))
Expect(model.TxHash).To(Equal(expectedApprovalModel.TxHash))
model := daiConverter.ToApprovalModel(result)
Expect(model).To(Equal(&expectedApprovalModel))
})
})

View File

@ -15,8 +15,9 @@
package event_triggered
import (
"github.com/ethereum/go-ethereum/common"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
type TransferEntity struct {

View File

@ -22,12 +22,8 @@ import (
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/examples/test_helpers"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"math/rand"
"time"
)
var transferLog = core.Log{
@ -36,7 +32,7 @@ var transferLog = core.Log{
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topics: [4]string{
constants.TransferEventSignature,
constants.TransferEvent.Signature(),
"0x000000000000000000000000000000000000000000000000000000000000af21",
"0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
"",
@ -50,7 +46,7 @@ var approvalLog = core.Log{
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topics: [4]string{
constants.ApprovalEventSignature,
constants.ApprovalEvent.Signature(),
"0x000000000000000000000000000000000000000000000000000000000000af21",
"0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
"",
@ -74,100 +70,65 @@ var logs = []core.Log{
var _ = Describe("Integration test with vulcanizedb", func() {
var db *postgres.DB
rand.Seed(time.Now().UnixNano())
BeforeEach(func() {
var err error
db, err = postgres.NewDB(config.Database{
Hostname: "localhost",
Name: "vulcanize_private",
Port: 5432,
}, core.Node{})
Expect(err).NotTo(HaveOccurred())
receiptRepository := repositories.ReceiptRepository{DB: db}
blockRepository := *repositories.NewBlockRepository(db)
blockNumber := rand.Int63()
blockId := test_helpers.CreateBlock(blockNumber, blockRepository)
receipt := core.Receipt{
Logs: logs,
}
receipts := []core.Receipt{receipt}
err = receiptRepository.CreateReceiptsAndLogs(blockId, receipts)
Expect(err).ToNot(HaveOccurred())
var vulcanizeLogIds []int64
err = db.Select(&vulcanizeLogIds, `SELECT id FROM logs`)
Expect(err).ToNot(HaveOccurred())
db = test_helpers.SetupIntegrationDB(db, logs)
})
AfterEach(func() {
_, err := db.Exec(`DELETE FROM token_transfers`)
Expect(err).ToNot(HaveOccurred())
_, err = db.Exec(`DELETE FROM token_approvals`)
Expect(err).ToNot(HaveOccurred())
_, err = db.Exec(`DELETE FROM log_filters`)
Expect(err).ToNot(HaveOccurred())
_, err = db.Exec(`DELETE FROM logs`)
Expect(err).ToNot(HaveOccurred())
db = test_helpers.TearDownIntegrationDB(db)
})
It("creates transfer entry for each Transfer event received", func() {
transformer := event_triggered.NewTransformer(db, generic.DaiConfig)
It("creates token_transfers entry for each Transfer event received", func() {
transformer, err := event_triggered.NewTransformer(db, generic.DaiConfig)
Expect(err).ToNot(HaveOccurred())
transformer.Execute()
var count int
err := db.QueryRow(`SELECT COUNT(*) FROM token_transfers`).Scan(&count)
err = db.QueryRow(`SELECT COUNT(*) FROM token_transfers`).Scan(&count)
Expect(err).ToNot(HaveOccurred())
Expect(count).To(Equal(1))
type dbRow struct {
DBID uint64 `db:"id"`
VulcanizeLogID int64 `db:"vulcanize_log_id"`
event_triggered.TransferModel
}
var transfer dbRow
err = db.Get(&transfer, `SELECT * FROM token_transfers WHERE block=$1`, logs[0].BlockNumber)
transfer := event_triggered.TransferModel{}
err = db.Get(&transfer, `SELECT
token_name,
token_address,
to_address,
from_address,
tokens,
block,
tx
FROM token_transfers WHERE block=$1`, logs[0].BlockNumber)
Expect(err).ToNot(HaveOccurred())
Expect(transfer.TokenName).To(Equal(expectedTransferModel.TokenName))
Expect(transfer.TokenAddress).To(Equal(expectedTransferModel.TokenAddress))
Expect(transfer.To).To(Equal(expectedTransferModel.To))
Expect(transfer.From).To(Equal(expectedTransferModel.From))
Expect(transfer.Tokens).To(Equal(expectedTransferModel.Tokens))
Expect(transfer.Block).To(Equal(expectedTransferModel.Block))
Expect(transfer.TxHash).To(Equal(expectedTransferModel.TxHash))
Expect(transfer).To(Equal(expectedTransferModel))
})
It("creates approval entry for each Approval event received", func() {
transformer := event_triggered.NewTransformer(db, generic.DaiConfig)
It("creates token_approvals entry for each Approval event received", func() {
transformer, err := event_triggered.NewTransformer(db, generic.DaiConfig)
Expect(err).ToNot(HaveOccurred())
transformer.Execute()
var count int
err := db.QueryRow(`SELECT COUNT(*) FROM token_approvals`).Scan(&count)
err = db.QueryRow(`SELECT COUNT(*) FROM token_approvals`).Scan(&count)
Expect(err).ToNot(HaveOccurred())
Expect(count).To(Equal(1))
type dbRow struct {
DBID uint64 `db:"id"`
VulcanizeLogID int64 `db:"vulcanize_log_id"`
event_triggered.ApprovalModel
}
var transfer dbRow
err = db.Get(&transfer, `SELECT * FROM token_approvals WHERE block=$1`, logs[0].BlockNumber)
approval := event_triggered.ApprovalModel{}
err = db.Get(&approval, `SELECT
token_name,
token_address,
owner,
spender,
tokens,
block,
tx
FROM token_approvals WHERE block=$1`, logs[0].BlockNumber)
Expect(err).ToNot(HaveOccurred())
Expect(transfer.TokenName).To(Equal(expectedApprovalModel.TokenName))
Expect(transfer.TokenAddress).To(Equal(expectedApprovalModel.TokenAddress))
Expect(transfer.Owner).To(Equal(expectedApprovalModel.Owner))
Expect(transfer.Spender).To(Equal(expectedApprovalModel.Spender))
Expect(transfer.Tokens).To(Equal(expectedApprovalModel.Tokens))
Expect(transfer.Block).To(Equal(expectedApprovalModel.Block))
Expect(transfer.TxHash).To(Equal(expectedApprovalModel.TxHash))
Expect(approval).To(Equal(expectedApprovalModel))
})
})

View File

@ -18,16 +18,16 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type Datastore interface {
CreateTransfer(model TransferModel, vulcanizeLogId int64) error
CreateApproval(model ApprovalModel, vulcanizeLogId int64) error
type ERC20EventDatastore interface {
CreateTransfer(model *TransferModel, vulcanizeLogId int64) error
CreateApproval(model *ApprovalModel, vulcanizeLogId int64) error
}
type Repository struct {
type ERC20EventRepository struct {
*postgres.DB
}
func (repository Repository) CreateTransfer(transferModel TransferModel, vulcanizeLogId int64) error {
func (repository ERC20EventRepository) CreateTransfer(transferModel *TransferModel, vulcanizeLogId int64) error {
_, err := repository.DB.Exec(
`INSERT INTO token_transfers (vulcanize_log_id, token_name, token_address, to_address, from_address, tokens, block, tx)
@ -35,14 +35,10 @@ func (repository Repository) CreateTransfer(transferModel TransferModel, vulcani
ON CONFLICT (vulcanize_log_id) DO NOTHING`,
vulcanizeLogId, transferModel.TokenName, transferModel.TokenAddress, transferModel.To, transferModel.From, transferModel.Tokens, transferModel.Block, transferModel.TxHash)
if err != nil {
return err
}
return nil
return err
}
func (repository Repository) CreateApproval(approvalModel ApprovalModel, vulcanizeLogId int64) error {
func (repository ERC20EventRepository) CreateApproval(approvalModel *ApprovalModel, vulcanizeLogId int64) error {
_, err := repository.DB.Exec(
`INSERT INTO token_approvals (vulcanize_log_id, token_name, token_address, owner, spender, tokens, block, tx)
@ -50,9 +46,5 @@ func (repository Repository) CreateApproval(approvalModel ApprovalModel, vulcani
ON CONFLICT (vulcanize_log_id) DO NOTHING`,
vulcanizeLogId, approvalModel.TokenName, approvalModel.TokenAddress, approvalModel.Owner, approvalModel.Spender, approvalModel.Tokens, approvalModel.Block, approvalModel.TxHash)
if err != nil {
return err
}
return nil
return err
}

View File

@ -15,9 +15,13 @@
package event_triggered_test
import (
"math/rand"
"time"
"github.com/ethereum/go-ethereum/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/generic/helpers"
"github.com/vulcanize/vulcanizedb/examples/test_helpers"
@ -25,11 +29,9 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"math/rand"
"time"
)
var transferEntity = event_triggered.TransferEntity{
var transferEntity = &event_triggered.TransferEntity{
TokenName: "Dai",
TokenAddress: common.HexToAddress("0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"),
Src: common.HexToAddress("0x000000000000000000000000000000000000Af21"),
@ -39,7 +41,7 @@ var transferEntity = event_triggered.TransferEntity{
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
}
var approvalEntity = event_triggered.ApprovalEntity{
var approvalEntity = &event_triggered.ApprovalEntity{
TokenName: "Dai",
TokenAddress: common.HexToAddress("0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"),
Src: common.HexToAddress("0x000000000000000000000000000000000000Af21"),
@ -51,7 +53,8 @@ var approvalEntity = event_triggered.ApprovalEntity{
var _ = Describe("Approval and Transfer Repository Tests", func() {
var db *postgres.DB
var repository event_triggered.Repository
var converter event_triggered.ERC20Converter
var repository event_triggered.ERC20EventRepository
var logRepository repositories.LogRepository
var blockRepository repositories.BlockRepository
var receiptRepository repositories.ReceiptRepository
@ -89,7 +92,8 @@ var _ = Describe("Approval and Transfer Repository Tests", func() {
err = logRepository.Get(&vulcanizeLogId, `SELECT id FROM logs`)
Expect(err).ToNot(HaveOccurred())
repository = event_triggered.Repository{DB: db}
repository = event_triggered.ERC20EventRepository{DB: db}
converter = event_triggered.ERC20Converter{}
})
@ -97,12 +101,11 @@ var _ = Describe("Approval and Transfer Repository Tests", func() {
db.Query(`DELETE FROM logs`)
db.Query(`DELETE FROM log_filters`)
db.Query(`DELETE FROM token_transfers`)
db.Query(`DELETE FROM token_approvals`)
repository.DB.Exec(`DELETE FROM token_transfers`)
})
It("Creates a new Transfer record", func() {
converter := event_triggered.ERC20Converter{}
model := converter.ToTransferModel(transferEntity)
err := repository.CreateTransfer(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
@ -127,7 +130,6 @@ var _ = Describe("Approval and Transfer Repository Tests", func() {
})
It("does not duplicate token_transfers that have already been seen", func() {
converter := event_triggered.ERC20Converter{}
model := converter.ToTransferModel(transferEntity)
err := repository.CreateTransfer(model, vulcanizeLogId)
@ -144,7 +146,6 @@ var _ = Describe("Approval and Transfer Repository Tests", func() {
It("Removes a Transfer record when the corresponding log is removed", func() {
var exists bool
converter := event_triggered.ERC20Converter{}
model := converter.ToTransferModel(transferEntity)
err := repository.CreateTransfer(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
@ -168,7 +169,6 @@ var _ = Describe("Approval and Transfer Repository Tests", func() {
})
It("Creates a new Approval record", func() {
converter := event_triggered.ERC20Converter{}
model := converter.ToApprovalModel(approvalEntity)
err := repository.CreateApproval(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
@ -193,7 +193,6 @@ var _ = Describe("Approval and Transfer Repository Tests", func() {
})
It("does not duplicate token_approvals that have already been seen", func() {
converter := event_triggered.ERC20Converter{}
model := converter.ToApprovalModel(approvalEntity)
err := repository.CreateApproval(model, vulcanizeLogId)
@ -210,7 +209,6 @@ var _ = Describe("Approval and Transfer Repository Tests", func() {
It("Removes a Approval record when the corresponding log is removed", func() {
var exists bool
converter := event_triggered.ERC20Converter{}
model := converter.ToApprovalModel(approvalEntity)
err := repository.CreateApproval(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())

View File

@ -15,9 +15,9 @@
package event_triggered
import (
"fmt"
"log"
"fmt"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/libraries/shared"
@ -26,50 +26,56 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
)
type DaiTransformer struct {
type ERC20EventTransformer struct {
Converter ERC20ConverterInterface
WatchedEventRepository datastore.WatchedEventRepository
FilterRepository datastore.FilterRepository
Repository Datastore
Repository ERC20EventDatastore
}
func NewTransformer(db *postgres.DB, config generic.ContractConfig) shared.Transformer {
func NewTransformer(db *postgres.DB, config generic.ContractConfig) (shared.Transformer, error) {
var transformer shared.Transformer
cnvtr := NewERC20Converter(config)
cnvtr, err := NewERC20Converter(config)
if err != nil {
return transformer, err
}
wer := repositories.WatchedEventRepository{DB: db}
fr := repositories.FilterRepository{DB: db}
lkr := Repository{DB: db}
transformer = &DaiTransformer{
lkr := ERC20EventRepository{DB: db}
transformer = ERC20EventTransformer{
Converter: cnvtr,
WatchedEventRepository: wer,
FilterRepository: fr,
Repository: lkr,
}
for _, filter := range constants.DaiFilters {
for _, filter := range constants.DaiERC20Filters {
fr.CreateFilter(filter)
}
return transformer
return transformer, nil
}
func (tr DaiTransformer) Execute() error {
for _, filter := range constants.DaiFilters {
func (tr ERC20EventTransformer) Execute() error {
for _, filter := range constants.DaiERC20Filters {
watchedEvents, err := tr.WatchedEventRepository.GetWatchedEvents(filter.Name)
if err != nil {
log.Println(fmt.Sprintf("Error fetching events for %s:", filter.Name), err)
return err
}
for _, we := range watchedEvents {
if filter.Name == "Transfer" {
if filter.Name == constants.TransferEvent.String() {
entity, err := tr.Converter.ToTransferEntity(*we)
model := tr.Converter.ToTransferModel(*entity)
model := tr.Converter.ToTransferModel(entity)
if err != nil {
log.Printf("Error persisting data for Dai Transfers (watchedEvent.LogID %d):\n %s", we.LogID, err)
}
tr.Repository.CreateTransfer(model, we.LogID)
}
if filter.Name == "Approval" {
if filter.Name == constants.ApprovalEvent.String() {
entity, err := tr.Converter.ToApprovalEntity(*we)
model := tr.Converter.ToApprovalModel(*entity)
model := tr.Converter.ToApprovalModel(entity)
if err != nil {
log.Printf("Error persisting data for Dai Approvals (watchedEvent.LogID %d):\n %s", we.LogID, err)
}

View File

@ -17,43 +17,13 @@ package event_triggered_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/mocks"
"github.com/vulcanize/vulcanizedb/pkg/core"
)
type MockERC20Converter struct {
watchedEvents []*core.WatchedEvent
transfersToConvert []event_triggered.TransferEntity
approvalsToConvert []event_triggered.ApprovalEntity
block int64
}
func (mlkc *MockERC20Converter) ToTransferModel(entity event_triggered.TransferEntity) event_triggered.TransferModel {
mlkc.transfersToConvert = append(mlkc.transfersToConvert, entity)
return event_triggered.TransferModel{}
}
func (mlkc *MockERC20Converter) ToTransferEntity(watchedEvent core.WatchedEvent) (*event_triggered.TransferEntity, error) {
mlkc.watchedEvents = append(mlkc.watchedEvents, &watchedEvent)
e := &event_triggered.TransferEntity{Block: watchedEvent.BlockNumber}
mlkc.block++
return e, nil
}
func (mlkc *MockERC20Converter) ToApprovalModel(entity event_triggered.ApprovalEntity) event_triggered.ApprovalModel {
mlkc.approvalsToConvert = append(mlkc.approvalsToConvert, entity)
return event_triggered.ApprovalModel{}
}
func (mlkc *MockERC20Converter) ToApprovalEntity(watchedEvent core.WatchedEvent) (*event_triggered.ApprovalEntity, error) {
mlkc.watchedEvents = append(mlkc.watchedEvents, &watchedEvent)
e := &event_triggered.ApprovalEntity{Block: watchedEvent.BlockNumber}
mlkc.block++
return e, nil
}
var blockID1 = int64(5428074)
var logID1 = int64(113)
var blockID2 = int64(5428405)
@ -62,12 +32,12 @@ var logID2 = int64(100)
var fakeWatchedEvents = []*core.WatchedEvent{
{
LogID: logID1,
Name: "Transfer",
Name: constants.TransferEvent.String(),
BlockNumber: blockID1,
Address: constants.DaiContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.TransferEventSignature,
Topic0: constants.TransferEvent.Signature(),
Topic1: "0x000000000000000000000000000000000000000000000000000000000000af21",
Topic2: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic3: "",
@ -75,12 +45,12 @@ var fakeWatchedEvents = []*core.WatchedEvent{
},
{
LogID: logID2,
Name: "Approval",
Name: constants.ApprovalEvent.String(),
BlockNumber: blockID2,
Address: constants.DaiContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.ApprovalEventSignature,
Topic0: constants.ApprovalEvent.Signature(),
Topic1: "0x000000000000000000000000000000000000000000000000000000000000af21",
Topic2: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic3: "",
@ -89,19 +59,20 @@ var fakeWatchedEvents = []*core.WatchedEvent{
}
var _ = Describe("Mock ERC20 transformer", func() {
var mockERC20Converter MockERC20Converter
var mockERC20Converter mocks.MockERC20Converter
var watchedEventsRepo mocks.MockWatchedEventsRepository
var mockEventRepo mocks.MockEventRepo
var filterRepo mocks.MockFilterRepository
var transformer event_triggered.DaiTransformer
var transformer event_triggered.ERC20EventTransformer
BeforeEach(func() {
mockERC20Converter = MockERC20Converter{}
mockERC20Converter = mocks.MockERC20Converter{}
watchedEventsRepo = mocks.MockWatchedEventsRepository{}
watchedEventsRepo.SetWatchedEvents(fakeWatchedEvents)
mockEventRepo = mocks.MockEventRepo{}
filterRepo = mocks.MockFilterRepository{}
transformer = event_triggered.DaiTransformer{
transformer = event_triggered.ERC20EventTransformer{
Converter: &mockERC20Converter,
WatchedEventRepository: &watchedEventsRepo,
FilterRepository: filterRepo,
@ -112,22 +83,22 @@ var _ = Describe("Mock ERC20 transformer", func() {
It("calls the watched events repo with correct filter", func() {
transformer.Execute()
Expect(len(watchedEventsRepo.Names)).To(Equal(2))
Expect(watchedEventsRepo.Names).To(ConsistOf([]string{"Transfer", "Approval"}))
Expect(watchedEventsRepo.Names).To(ConsistOf([]string{constants.TransferEvent.String(), constants.ApprovalEvent.String()}))
})
It("calls the mock ERC20 converter with the watched events", func() {
transformer.Execute()
Expect(len(mockERC20Converter.watchedEvents)).To(Equal(2))
Expect(mockERC20Converter.watchedEvents).To(ConsistOf(fakeWatchedEvents))
Expect(len(mockERC20Converter.WatchedEvents)).To(Equal(2))
Expect(mockERC20Converter.WatchedEvents).To(ConsistOf(fakeWatchedEvents))
})
It("converts a Transfer entity to a model", func() {
It("converts a Transfer and Approval entity to their models", func() {
transformer.Execute()
Expect(len(mockERC20Converter.transfersToConvert)).To(Equal(1))
Expect(mockERC20Converter.transfersToConvert[0].Block).To(Equal(blockID1))
Expect(len(mockERC20Converter.TransfersToConvert)).To(Equal(1))
Expect(mockERC20Converter.TransfersToConvert[0].Block).To(Equal(blockID1))
Expect(len(mockERC20Converter.approvalsToConvert)).To(Equal(1))
Expect(mockERC20Converter.approvalsToConvert[0].Block).To(Equal(blockID2))
Expect(len(mockERC20Converter.ApprovalsToConvert)).To(Equal(1))
Expect(mockERC20Converter.ApprovalsToConvert[0].Block).To(Equal(blockID2))
})
It("persists Transfer and Approval data for each watched Transfer or Approval event", func() {

View File

@ -15,12 +15,12 @@
package every_block_test
import (
"io/ioutil"
"log"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"io/ioutil"
"log"
)
func TestEveryBlock(t *testing.T) {

View File

@ -32,13 +32,13 @@ type ERC20GetterInterface interface {
}
// Getter struct
type Getter struct {
type ERC20Getter struct {
fetcher generic.Fetcher
}
// Initializes and returns a Getter with the given blockchain
func NewGetter(blockChain core.BlockChain) Getter {
return Getter{
func NewGetter(blockChain core.BlockChain) ERC20Getter {
return ERC20Getter{
fetcher: generic.Fetcher{
BlockChain: blockChain,
},
@ -46,19 +46,19 @@ func NewGetter(blockChain core.BlockChain) Getter {
}
// Public getter methods for calling contract methods
func (g Getter) GetTotalSupply(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) {
func (g ERC20Getter) GetTotalSupply(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) {
return g.fetcher.FetchBigInt("totalSupply", contractAbi, contractAddress, blockNumber, nil)
}
func (g Getter) GetBalance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) {
func (g ERC20Getter) GetBalance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) {
return g.fetcher.FetchBigInt("balanceOf", contractAbi, contractAddress, blockNumber, methodArgs)
}
func (g Getter) GetAllowance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) {
func (g ERC20Getter) GetAllowance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) {
return g.fetcher.FetchBigInt("allowance", contractAbi, contractAddress, blockNumber, methodArgs)
}
// Method to retrieve the Getter's blockchain
func (g Getter) GetBlockChain() core.BlockChain {
func (g ERC20Getter) GetBlockChain() core.BlockChain {
return g.fetcher.BlockChain
}

View File

@ -17,12 +17,12 @@ package every_block_test
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block"
"github.com/vulcanize/vulcanizedb/pkg/fakes"

View File

@ -15,8 +15,12 @@
package every_block_test
import (
"math/big"
"strconv"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block"
"github.com/vulcanize/vulcanizedb/examples/generic"
@ -25,8 +29,6 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"math/big"
"strconv"
)
func setLastBlockOnChain(blockChain *fakes.MockBlockChain, blockNumber int64) {

View File

@ -16,12 +16,13 @@ package every_block
import (
"fmt"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"log"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
// Interface definition for a generic ERC20 token repository
type ERC20RepositoryInterface interface {
type ERC20TokenDatastore interface {
CreateSupply(supply TokenSupply) error
CreateBalance(balance TokenBalance) error
CreateAllowance(allowance TokenAllowance) error

View File

@ -15,6 +15,8 @@
package every_block_test
import (
"math/rand"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -24,7 +26,6 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/test_config"
"math/rand"
)
var _ = Describe("ERC20 Token Supply Repository", func() {

View File

@ -16,23 +16,25 @@ package every_block
import (
"fmt"
"log"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/libraries/shared"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"log"
"math/big"
)
type Transformer struct {
type ERC20Transformer struct {
Getter ERC20GetterInterface
Repository ERC20RepositoryInterface
Retriever generic.Retriever
Repository ERC20TokenDatastore
Retriever generic.TokenHolderRetriever
Config generic.ContractConfig
}
func (t *Transformer) SetConfiguration(config generic.ContractConfig) {
func (t *ERC20Transformer) SetConfiguration(config generic.ContractConfig) {
t.Config = config
}
@ -43,8 +45,8 @@ type ERC20TokenTransformerInitializer struct {
func (i ERC20TokenTransformerInitializer) NewERC20TokenTransformer(db *postgres.DB, blockchain core.BlockChain) shared.Transformer {
getter := NewGetter(blockchain)
repository := ERC20TokenRepository{DB: db}
retriever := generic.NewRetriever(db, i.Config.Address)
transformer := Transformer{
retriever := generic.NewTokenHolderRetriever(db, i.Config.Address)
transformer := ERC20Transformer{
Getter: &getter,
Repository: &repository,
Retriever: retriever,
@ -81,7 +83,7 @@ func newTransformerError(err error, blockNumber int64, msg string) error {
return &e
}
func (t Transformer) Execute() error {
func (t ERC20Transformer) Execute() error {
var upperBoundBlock int64
blockchain := t.Getter.GetBlockChain()
lastBlock := blockchain.LastBlock().Int64()

View File

@ -15,17 +15,19 @@
package every_block_test
import (
"math/big"
"math/rand"
"strconv"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/examples/mocks"
"github.com/vulcanize/vulcanizedb/examples/test_helpers"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"math/big"
"math/rand"
"strconv"
)
var testContractConfig = generic.ContractConfig{
@ -41,7 +43,7 @@ var config = testContractConfig
var _ = Describe("Everyblock transformer", func() {
var getter mocks.Getter
var repository mocks.ERC20TokenRepository
var transformer every_block.Transformer
var transformer every_block.ERC20Transformer
var blockChain *fakes.MockBlockChain
var initialSupply = "27647235749155415536952630"
var initialSupplyPlusOne = "27647235749155415536952631"
@ -57,10 +59,10 @@ var _ = Describe("Everyblock transformer", func() {
repository = mocks.ERC20TokenRepository{}
repository.SetMissingSupplyBlocks([]int64{config.FirstBlock})
db := test_helpers.CreateNewDatabase()
rt := generic.NewRetriever(db, config.Address)
rt := generic.NewTokenHolderRetriever(db, config.Address)
//setting the mock repository to return the first block as the missing blocks
transformer = every_block.Transformer{
transformer = every_block.ERC20Transformer{
Getter: &getter,
Repository: &repository,
Retriever: rt,
@ -150,7 +152,7 @@ var _ = Describe("Everyblock transformer", func() {
It("returns an error if the call to get missing blocks fails", func() {
failureRepository := mocks.FailureRepository{}
failureRepository.SetMissingSupplyBlocksFail(true)
transformer = every_block.Transformer{
transformer = every_block.ERC20Transformer{
Getter: &getter,
Repository: &failureRepository,
}
@ -165,7 +167,7 @@ var _ = Describe("Everyblock transformer", func() {
failureBlockchain.SetLastBlock(&defaultLastBlock)
failureBlockchain.SetFetchContractDataErr(fakes.FakeError)
getter := every_block.NewGetter(failureBlockchain)
transformer = every_block.Transformer{
transformer = every_block.ERC20Transformer{
Getter: &getter,
Repository: &repository,
}
@ -180,7 +182,7 @@ var _ = Describe("Everyblock transformer", func() {
failureRepository.SetMissingSupplyBlocks([]int64{config.FirstBlock})
failureRepository.SetCreateSupplyFail(true)
transformer = every_block.Transformer{
transformer = every_block.ERC20Transformer{
Getter: &getter,
Repository: &failureRepository,
}

View File

@ -21,6 +21,7 @@ import (
type ContractConfig struct {
Address string
Owner string
Abi string
ParsedAbi abi.ABI
FirstBlock int64
@ -30,9 +31,18 @@ type ContractConfig struct {
var DaiConfig = ContractConfig{
Address: constants.DaiContractAddress,
Owner: constants.DaiContractOwner,
Abi: constants.DaiAbiString,
ParsedAbi: constants.ParsedDaiAbi,
FirstBlock: int64(4752008),
LastBlock: -1,
Name: "Dai",
}
var TusdConfig = ContractConfig{
Address: constants.TusdContractAddress,
Owner: constants.TusdContractOwner,
Abi: constants.TusdAbiString,
FirstBlock: int64(5197514),
LastBlock: -1,
Name: "Tusd",
}

View File

@ -0,0 +1,117 @@
// 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 event_triggered
import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/examples/generic/helpers"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/geth"
)
// Converter converts a raw event log into its corresponding entity
// and can subsequently convert the entity into a model
type GenericConverterInterface interface {
ToBurnEntity(watchedEvent core.WatchedEvent) (*BurnEntity, error)
ToBurnModel(entity *BurnEntity) *BurnModel
ToMintEntity(watchedEvent core.WatchedEvent) (*MintEntity, error)
ToMintModel(entity *MintEntity) *MintModel
}
type GenericConverter struct {
config generic.ContractConfig
}
func NewGenericConverter(config generic.ContractConfig) (*GenericConverter, error) {
var err error
config.ParsedAbi, err = geth.ParseAbi(config.Abi)
if err != nil {
return nil, err
}
converter := &GenericConverter{
config: config,
}
return converter, nil
}
func (c GenericConverter) ToBurnEntity(watchedEvent core.WatchedEvent) (*BurnEntity, error) {
result := &BurnEntity{}
contract := bind.NewBoundContract(common.HexToAddress(c.config.Address), c.config.ParsedAbi, nil, nil, nil)
event := helpers.ConvertToLog(watchedEvent)
err := contract.UnpackLog(result, constants.BurnEvent.String(), event)
if err != nil {
return result, err
}
result.TokenName = c.config.Name
result.TokenAddress = common.HexToAddress(c.config.Address)
result.Block = watchedEvent.BlockNumber
result.TxHash = watchedEvent.TxHash
return result, nil
}
func (c GenericConverter) ToBurnModel(entity *BurnEntity) *BurnModel {
burner := entity.Burner.String()
tokens := entity.Value.String()
return &BurnModel{
TokenName: c.config.Name,
TokenAddress: c.config.Address,
Burner: burner,
Tokens: tokens,
Block: entity.Block,
TxHash: entity.TxHash,
}
}
func (c GenericConverter) ToMintEntity(watchedEvent core.WatchedEvent) (*MintEntity, error) {
result := &MintEntity{}
contract := bind.NewBoundContract(common.HexToAddress(c.config.Address), c.config.ParsedAbi, nil, nil, nil)
event := helpers.ConvertToLog(watchedEvent)
err := contract.UnpackLog(result, constants.MintEvent.String(), event)
if err != nil {
return result, err
}
result.TokenName = c.config.Name
result.TokenAddress = common.HexToAddress(c.config.Address)
result.Block = watchedEvent.BlockNumber
result.TxHash = watchedEvent.TxHash
return result, nil
}
func (c GenericConverter) ToMintModel(entity *MintEntity) *MintModel {
mintee := entity.To.String()
minter := c.config.Owner
tokens := entity.Amount.String()
return &MintModel{
TokenName: c.config.Name,
TokenAddress: c.config.Address,
Mintee: mintee,
Minter: minter,
Tokens: tokens,
Block: entity.Block,
TxHash: entity.TxHash,
}
}

View File

@ -0,0 +1,148 @@
// 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 event_triggered_test
import (
"github.com/ethereum/go-ethereum/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/examples/generic/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/generic/helpers"
"github.com/vulcanize/vulcanizedb/pkg/core"
)
var expectedBurnModel = event_triggered.BurnModel{
TokenName: "Tusd",
TokenAddress: constants.TusdContractAddress,
Burner: "0x09BbBBE21a5975cAc061D82f7b843bCE061BA391",
Tokens: "1097077688018008265106216665536940668749033598146",
Block: 5488076,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
}
var expectedBurnEntity = event_triggered.BurnEntity{
TokenName: "Tusd",
TokenAddress: common.HexToAddress(constants.TusdContractAddress),
Burner: common.HexToAddress("0x09BbBBE21a5975cAc061D82f7b843bCE061BA391"),
Value: helpers.BigFromString("1097077688018008265106216665536940668749033598146"),
Block: 5488076,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
}
var expectedMintModel = event_triggered.MintModel{
TokenName: "Tusd",
TokenAddress: constants.TusdContractAddress,
Minter: constants.TusdContractOwner,
Mintee: "0x09BbBBE21a5975cAc061D82f7b843bCE061BA391",
Tokens: "1097077688018008265106216665536940668749033598146",
Block: 5488076,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
}
var expectedMintEntity = event_triggered.MintEntity{
TokenName: "Tusd",
TokenAddress: common.HexToAddress(constants.TusdContractAddress),
To: common.HexToAddress("0x09BbBBE21a5975cAc061D82f7b843bCE061BA391"),
Amount: helpers.BigFromString("1097077688018008265106216665536940668749033598146"),
Block: 5488076,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
}
var burnEvent = core.WatchedEvent{
LogID: 1,
Name: constants.BurnEvent.String(),
BlockNumber: 5488076,
Address: constants.TusdContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.BurnEvent.Signature(),
Topic1: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic2: "",
Topic3: "",
Data: "0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000000000000000000000000000392d2e2bda9c00000000000000000000000000000000000000000000000000927f41fa0a4a418000000000000000000000000000000000000000000000000000000000005adcfebe",
}
var mintEvent = core.WatchedEvent{
LogID: 1,
Name: constants.MintEvent.String(),
BlockNumber: 5488076,
Address: constants.TusdContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.MintEvent.Signature(),
Topic1: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic2: "",
Topic3: "",
Data: "0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000000000000000000000000000392d2e2bda9c00000000000000000000000000000000000000000000000000927f41fa0a4a418000000000000000000000000000000000000000000000000000000000005adcfebe",
}
var _ = Describe("Transfer Converter", func() {
var converter *event_triggered.GenericConverter
var err error
BeforeEach(func() {
converter, err = event_triggered.NewGenericConverter(generic.TusdConfig)
Expect(err).NotTo(HaveOccurred())
})
It("converts a watched burn event into a BurnEntity", func() {
result, err := converter.ToBurnEntity(burnEvent)
Expect(err).NotTo(HaveOccurred())
Expect(result).To(Equal(&expectedBurnEntity))
})
It("converts a BurnEntity to a BurnModel", func() {
result, err := converter.ToBurnEntity(burnEvent)
Expect(err).NotTo(HaveOccurred())
model := converter.ToBurnModel(result)
Expect(model).To(Equal(&expectedBurnModel))
})
})
var _ = Describe("Approval Converter", func() {
var converter *event_triggered.GenericConverter
var err error
BeforeEach(func() {
converter, err = event_triggered.NewGenericConverter(generic.TusdConfig)
Expect(err).NotTo(HaveOccurred())
})
It("converts a watched mint event into a MintEntity", func() {
result, err := converter.ToMintEntity(mintEvent)
Expect(err).NotTo(HaveOccurred())
Expect(result).To(Equal(&expectedMintEntity))
})
It("converts a MintEntity to a MintModel", func() {
result, err := converter.ToMintEntity(mintEvent)
Expect(err).NotTo(HaveOccurred())
model := converter.ToMintModel(result)
Expect(model).To(Equal(&expectedMintModel))
})
})

View File

@ -0,0 +1,39 @@
// 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 event_triggered
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
)
type BurnEntity struct {
TokenName string
TokenAddress common.Address
Burner common.Address
Value *big.Int
Block int64
TxHash string
}
type MintEntity struct {
TokenName string
TokenAddress common.Address
To common.Address
Amount *big.Int
Block int64
TxHash string
}

View File

@ -0,0 +1,27 @@
// 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 event_triggered_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestLogKill(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "ERC20 Event Triggered test Suite")
}

View File

@ -0,0 +1,133 @@
// 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 event_triggered_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/examples/generic/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/test_helpers"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
var burnLog = core.Log{
BlockNumber: 5488076,
Address: constants.TusdContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topics: [4]string{
constants.BurnEvent.Signature(),
"0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
"",
"",
},
Data: "0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000000000000000000000000000392d2e2bda9c00000000000000000000000000000000000000000000000000927f41fa0a4a418000000000000000000000000000000000000000000000000000000000005adcfebe",
}
var mintLog = core.Log{
BlockNumber: 5488076,
Address: constants.TusdContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topics: [4]string{
constants.MintEvent.Signature(),
"0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
"",
"",
},
Data: "0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000000000000000000000000000392d2e2bda9c00000000000000000000000000000000000000000000000000927f41fa0a4a418000000000000000000000000000000000000000000000000000000000005adcfebe",
}
//converted transfer to assert against
var logs = []core.Log{
burnLog,
mintLog,
{
BlockNumber: 0,
TxHash: "",
Address: "",
Topics: core.Topics{},
Index: 0,
Data: "",
},
}
var _ = Describe("Integration test with vulcanizedb", func() {
var db *postgres.DB
BeforeEach(func() {
db = test_helpers.SetupIntegrationDB(db, logs)
})
AfterEach(func() {
db = test_helpers.TearDownIntegrationDB(db)
})
It("creates token_burns entry for each Burn event received", func() {
transformer, err := event_triggered.NewTransformer(db, generic.TusdConfig)
Expect(err).ToNot(HaveOccurred())
transformer.Execute()
var count int
err = db.QueryRow(`SELECT COUNT(*) FROM token_burns`).Scan(&count)
Expect(err).ToNot(HaveOccurred())
Expect(count).To(Equal(1))
burn := event_triggered.BurnModel{}
err = db.Get(&burn, `SELECT
token_name,
token_address,
burner,
tokens,
block,
tx
FROM token_burns WHERE block=$1`, logs[0].BlockNumber)
Expect(err).ToNot(HaveOccurred())
Expect(burn).To(Equal(expectedBurnModel))
})
It("creates token_mints entry for each Mint event received", func() {
transformer, err := event_triggered.NewTransformer(db, generic.TusdConfig)
Expect(err).ToNot(HaveOccurred())
transformer.Execute()
var count int
err = db.QueryRow(`SELECT COUNT(*) FROM token_mints`).Scan(&count)
Expect(err).ToNot(HaveOccurred())
Expect(count).To(Equal(1))
mint := event_triggered.MintModel{}
err = db.Get(&mint, `SELECT
token_name,
token_address,
minter,
mintee,
tokens,
block,
tx
FROM token_mints WHERE block=$1`, logs[0].BlockNumber)
Expect(err).ToNot(HaveOccurred())
Expect(mint).To(Equal(expectedMintModel))
})
})

View File

@ -0,0 +1,34 @@
// 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 event_triggered
type BurnModel struct {
TokenName string `db:"token_name"`
TokenAddress string `db:"token_address"`
Burner string `db:"burner"`
Tokens string `db:"tokens"`
Block int64 `db:"block"`
TxHash string `db:"tx"`
}
type MintModel struct {
TokenName string `db:"token_name"`
TokenAddress string `db:"token_address"`
Mintee string `db:"mintee"`
Minter string `db:"minter"`
Tokens string `db:"tokens"`
Block int64 `db:"block"`
TxHash string `db:"tx"`
}

View File

@ -0,0 +1,50 @@
// 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 event_triggered
import (
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type GenericEventDatastore interface {
CreateBurn(model *BurnModel, vulcanizeLogId int64) error
CreateMint(model *MintModel, vulcanizeLogId int64) error
}
type GenericEventRepository struct {
*postgres.DB
}
func (repository GenericEventRepository) CreateBurn(burnModel *BurnModel, vulcanizeLogId int64) error {
_, err := repository.DB.Exec(
`INSERT INTO token_burns (vulcanize_log_id, token_name, token_address, burner, tokens, block, tx)
VALUES ($1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (vulcanize_log_id) DO NOTHING`,
vulcanizeLogId, burnModel.TokenName, burnModel.TokenAddress, burnModel.Burner, burnModel.Tokens, burnModel.Block, burnModel.TxHash)
return err
}
func (repository GenericEventRepository) CreateMint(mintModel *MintModel, vulcanizeLogId int64) error {
_, err := repository.DB.Exec(
`INSERT INTO token_mints (vulcanize_log_id, token_name, token_address, minter, mintee, tokens, block, tx)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (vulcanize_log_id) DO NOTHING`,
vulcanizeLogId, mintModel.TokenName, mintModel.TokenAddress, mintModel.Minter, mintModel.Mintee, mintModel.Tokens, mintModel.Block, mintModel.TxHash)
return err
}

View File

@ -0,0 +1,229 @@
// 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 event_triggered_test
import (
"math/rand"
"time"
"github.com/ethereum/go-ethereum/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/generic/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/generic/helpers"
"github.com/vulcanize/vulcanizedb/examples/test_helpers"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
)
var burnEntity = &event_triggered.BurnEntity{
TokenName: "Tusd",
TokenAddress: common.HexToAddress("0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"),
Burner: common.HexToAddress("0x09BbBBE21a5975cAc061D82f7b843bCE061BA391"),
Value: helpers.BigFromString("1097077688018008265106216665536940668749033598146"),
Block: 5488076,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
}
var mintEntity = &event_triggered.MintEntity{
TokenName: "Tusd",
TokenAddress: common.HexToAddress("0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359"),
To: common.HexToAddress("0x09BbBBE21a5975cAc061D82f7b843bCE061BA391"),
Amount: helpers.BigFromString("1097077688018008265106216665536940668749033598146"),
Block: 5488076,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
}
var _ = Describe("Approval and Transfer Repository Tests", func() {
var db *postgres.DB
var converter event_triggered.GenericConverter
var repository event_triggered.GenericEventRepository
var logRepository repositories.LogRepository
var blockRepository repositories.BlockRepository
var receiptRepository repositories.ReceiptRepository
var blockNumber int64
var blockId int64
var vulcanizeLogId int64
rand.Seed(time.Now().UnixNano())
BeforeEach(func() {
var err error
db, err = postgres.NewDB(config.Database{
Hostname: "localhost",
Name: "vulcanize_private",
Port: 5432,
}, core.Node{})
Expect(err).NotTo(HaveOccurred())
receiptRepository = repositories.ReceiptRepository{DB: db}
logRepository = repositories.LogRepository{DB: db}
blockRepository = *repositories.NewBlockRepository(db)
blockNumber = rand.Int63()
blockId = test_helpers.CreateBlock(blockNumber, blockRepository)
log := core.Log{}
logs := []core.Log{log}
receipt := core.Receipt{
Logs: logs,
}
receipts := []core.Receipt{receipt}
err = receiptRepository.CreateReceiptsAndLogs(blockId, receipts)
Expect(err).ToNot(HaveOccurred())
err = logRepository.Get(&vulcanizeLogId, `SELECT id FROM logs`)
Expect(err).ToNot(HaveOccurred())
repository = event_triggered.GenericEventRepository{DB: db}
converter = event_triggered.GenericConverter{}
})
AfterEach(func() {
db.Query(`DELETE FROM logs`)
db.Query(`DELETE FROM log_filters`)
db.Query(`DELETE FROM token_burns`)
db.Query(`DELETE FROM token_mints`)
})
It("Creates a new Burn record", func() {
model := converter.ToBurnModel(burnEntity)
err := repository.CreateBurn(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
type DBRow struct {
DBID uint64 `db:"id"`
VulcanizeLogID int64 `db:"vulcanize_log_id"`
event_triggered.BurnModel
}
dbResult := DBRow{}
err = repository.QueryRowx(`SELECT * FROM token_burns`).StructScan(&dbResult)
Expect(err).ToNot(HaveOccurred())
Expect(dbResult.VulcanizeLogID).To(Equal(vulcanizeLogId))
Expect(dbResult.TokenName).To(Equal(model.TokenName))
Expect(dbResult.TokenAddress).To(Equal(model.TokenAddress))
Expect(dbResult.Burner).To(Equal(model.Burner))
Expect(dbResult.Tokens).To(Equal(model.Tokens))
Expect(dbResult.Block).To(Equal(model.Block))
Expect(dbResult.TxHash).To(Equal(model.TxHash))
})
It("does not duplicate token_transfers that have already been seen", func() {
model := converter.ToBurnModel(burnEntity)
err := repository.CreateBurn(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
err = repository.CreateBurn(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
var count int
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_burns`).Scan(&count)
Expect(err).ToNot(HaveOccurred())
Expect(count).To(Equal(1))
})
It("Removes a Burn record when the corresponding log is removed", func() {
var exists bool
model := converter.ToBurnModel(burnEntity)
err := repository.CreateBurn(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
err = repository.DB.QueryRow(`SELECT exists (SELECT * FROM token_burns WHERE vulcanize_log_id = $1)`, vulcanizeLogId).Scan(&exists)
Expect(err).ToNot(HaveOccurred())
Expect(exists).To(BeTrue())
var logCount int
_, err = logRepository.DB.Exec(`DELETE FROM logs WHERE id = $1`, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
err = logRepository.Get(&logCount, `SELECT count(*) FROM logs WHERE id = $1`, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
Expect(logCount).To(BeZero())
var LogKillCount int
err = repository.DB.QueryRowx(
`SELECT count(*) FROM token_burns WHERE vulcanize_log_id = $1`, vulcanizeLogId).Scan(&LogKillCount)
Expect(err).ToNot(HaveOccurred())
Expect(LogKillCount).To(BeZero())
})
It("Creates a new Mint record", func() {
model := converter.ToMintModel(mintEntity)
err := repository.CreateMint(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
type DBRow struct {
DBID uint64 `db:"id"`
VulcanizeLogID int64 `db:"vulcanize_log_id"`
event_triggered.MintModel
}
dbResult := DBRow{}
err = repository.QueryRowx(`SELECT * FROM token_mints`).StructScan(&dbResult)
Expect(err).ToNot(HaveOccurred())
Expect(dbResult.VulcanizeLogID).To(Equal(vulcanizeLogId))
Expect(dbResult.TokenName).To(Equal(model.TokenName))
Expect(dbResult.TokenAddress).To(Equal(model.TokenAddress))
Expect(dbResult.Mintee).To(Equal(model.Mintee))
Expect(dbResult.Minter).To(Equal(model.Minter))
Expect(dbResult.Tokens).To(Equal(model.Tokens))
Expect(dbResult.Block).To(Equal(model.Block))
Expect(dbResult.TxHash).To(Equal(model.TxHash))
})
It("does not duplicate token_mints that have already been seen", func() {
model := converter.ToMintModel(mintEntity)
err := repository.CreateMint(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
err = repository.CreateMint(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
var count int
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_mints`).Scan(&count)
Expect(err).ToNot(HaveOccurred())
Expect(count).To(Equal(1))
})
It("Removes a Mint record when the corresponding log is removed", func() {
var exists bool
model := converter.ToMintModel(mintEntity)
err := repository.CreateMint(model, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
err = repository.DB.QueryRow(`SELECT exists (SELECT * FROM token_mints WHERE vulcanize_log_id = $1)`, vulcanizeLogId).Scan(&exists)
Expect(err).ToNot(HaveOccurred())
Expect(exists).To(BeTrue())
var logCount int
_, err = logRepository.DB.Exec(`DELETE FROM logs WHERE id = $1`, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
err = logRepository.Get(&logCount, `SELECT count(*) FROM logs WHERE id = $1`, vulcanizeLogId)
Expect(err).ToNot(HaveOccurred())
Expect(logCount).To(BeZero())
var LogKillCount int
err = repository.DB.QueryRowx(
`SELECT count(*) FROM token_mints WHERE vulcanize_log_id = $1`, vulcanizeLogId).Scan(&LogKillCount)
Expect(err).ToNot(HaveOccurred())
Expect(LogKillCount).To(BeZero())
})
})

View File

@ -0,0 +1,87 @@
// 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 event_triggered
import (
"fmt"
"log"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/libraries/shared"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
)
type GenericTransformer struct {
Converter GenericConverterInterface
WatchedEventRepository datastore.WatchedEventRepository
FilterRepository datastore.FilterRepository
Repository GenericEventDatastore
}
func NewTransformer(db *postgres.DB, config generic.ContractConfig) (shared.Transformer, error) {
var transformer shared.Transformer
cnvtr, err := NewGenericConverter(config)
if err != nil {
return transformer, err
}
wer := repositories.WatchedEventRepository{DB: db}
fr := repositories.FilterRepository{DB: db}
lkr := GenericEventRepository{DB: db}
transformer = GenericTransformer{
Converter: cnvtr,
WatchedEventRepository: wer,
FilterRepository: fr,
Repository: lkr,
}
for _, filter := range constants.TusdGenericFilters {
fr.CreateFilter(filter)
}
return transformer, nil
}
func (tr GenericTransformer) Execute() error {
for _, filter := range constants.TusdGenericFilters {
watchedEvents, err := tr.WatchedEventRepository.GetWatchedEvents(filter.Name)
if err != nil {
log.Println(fmt.Sprintf("Error fetching events for %s:", filter.Name), err)
return err
}
for _, we := range watchedEvents {
if filter.Name == constants.BurnEvent.String() {
entity, err := tr.Converter.ToBurnEntity(*we)
model := tr.Converter.ToBurnModel(entity)
if err != nil {
log.Printf("Error persisting data for Dai Burns (watchedEvent.LogID %d):\n %s", we.LogID, err)
}
tr.Repository.CreateBurn(model, we.LogID)
}
if filter.Name == constants.MintEvent.String() {
entity, err := tr.Converter.ToMintEntity(*we)
model := tr.Converter.ToMintModel(entity)
if err != nil {
log.Printf("Error persisting data for Dai Mints (watchedEvent.LogID %d):\n %s", we.LogID, err)
}
tr.Repository.CreateMint(model, we.LogID)
}
}
}
return nil
}

View File

@ -0,0 +1,111 @@
// 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 event_triggered_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic/event_triggered"
"github.com/vulcanize/vulcanizedb/examples/mocks"
"github.com/vulcanize/vulcanizedb/pkg/core"
)
var blockID1 = int64(5428074)
var logID1 = int64(113)
var blockID2 = int64(5428405)
var logID2 = int64(100)
var fakeWatchedEvents = []*core.WatchedEvent{
{
LogID: logID1,
Name: constants.BurnEvent.String(),
BlockNumber: blockID1,
Address: constants.TusdContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.BurnEvent.Signature(),
Topic1: "0x000000000000000000000000000000000000000000000000000000000000af21",
Topic2: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic3: "",
Data: "0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000000000000000000000000000392d2e2bda9c00000000000000000000000000000000000000000000000000927f41fa0a4a418000000000000000000000000000000000000000000000000000000000005adcfebe",
},
{
LogID: logID2,
Name: constants.MintEvent.String(),
BlockNumber: blockID2,
Address: constants.TusdContractAddress,
TxHash: "0x135391a0962a63944e5908e6fedfff90fb4be3e3290a21017861099bad6546ae",
Index: 110,
Topic0: constants.MintEvent.Signature(),
Topic1: "0x000000000000000000000000000000000000000000000000000000000000af21",
Topic2: "0x9dd48110dcc444fdc242510c09bbbbe21a5975cac061d82f7b843bce061ba391",
Topic3: "",
Data: "0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359000000000000000000000000000000000000000000000000392d2e2bda9c00000000000000000000000000000000000000000000000000927f41fa0a4a418000000000000000000000000000000000000000000000000000000000005adcfebe",
},
}
var _ = Describe("Mock ERC20 transformer", func() {
var mockERC20Converter mocks.MockERC20Converter
var watchedEventsRepo mocks.MockWatchedEventsRepository
var mockEventRepo mocks.MockEventRepo
var filterRepo mocks.MockFilterRepository
var transformer event_triggered.GenericTransformer
BeforeEach(func() {
mockERC20Converter = mocks.MockERC20Converter{}
watchedEventsRepo = mocks.MockWatchedEventsRepository{}
watchedEventsRepo.SetWatchedEvents(fakeWatchedEvents)
mockEventRepo = mocks.MockEventRepo{}
filterRepo = mocks.MockFilterRepository{}
transformer = event_triggered.GenericTransformer{
Converter: &mockERC20Converter,
WatchedEventRepository: &watchedEventsRepo,
FilterRepository: filterRepo,
Repository: &mockEventRepo,
}
})
It("calls the watched events repo with correct filter", func() {
transformer.Execute()
Expect(len(watchedEventsRepo.Names)).To(Equal(2))
Expect(watchedEventsRepo.Names).To(ConsistOf([]string{constants.BurnEvent.String(), constants.MintEvent.String()}))
})
It("calls the mock ERC20 converter with the watched events", func() {
transformer.Execute()
Expect(len(mockERC20Converter.WatchedEvents)).To(Equal(2))
Expect(mockERC20Converter.WatchedEvents).To(ConsistOf(fakeWatchedEvents))
})
It("converts a Burn and Mint entity to their models", func() {
transformer.Execute()
Expect(len(mockERC20Converter.BurnsToConvert)).To(Equal(1))
Expect(mockERC20Converter.BurnsToConvert[0].Block).To(Equal(blockID1))
Expect(len(mockERC20Converter.MintsToConvert)).To(Equal(1))
Expect(mockERC20Converter.MintsToConvert[0].Block).To(Equal(blockID2))
})
It("persists Burn and Mint data for each watched Burn or Mint event", func() {
transformer.Execute()
Expect(len(mockEventRepo.BurnLogs)).To(Equal(1))
Expect(len(mockEventRepo.MintLogs)).To(Equal(1))
Expect(mockEventRepo.VulcanizeLogIDs).To(ConsistOf(logID1, logID2))
})
})

View File

@ -15,12 +15,12 @@
package every_block_test
import (
"io/ioutil"
"log"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"io/ioutil"
"log"
)
func TestEveryBlock(t *testing.T) {

View File

@ -15,10 +15,12 @@
package every_block
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/examples/generic"
"github.com/vulcanize/vulcanizedb/pkg/core"
"math/big"
)
// Getter serves as a higher level data fetcher that invokes its underlying Fetcher methods for a given contract method
@ -36,13 +38,13 @@ type GenericGetterInterface interface {
}
// Getter struct
type Getter struct {
type GenericGetter struct {
fetcher generic.Fetcher // Underlying Fetcher
}
// Initializes and returns a Getter with the given blockchain
func NewGetter(blockChain core.BlockChain) Getter {
return Getter{
func NewGetter(blockChain core.BlockChain) GenericGetter {
return GenericGetter{
fetcher: generic.Fetcher{
BlockChain: blockChain,
},
@ -50,35 +52,35 @@ func NewGetter(blockChain core.BlockChain) Getter {
}
// Public getter methods for calling contract methods
func (g Getter) GetOwner(contractAbi, contractAddress string, blockNumber int64) (common.Address, error) {
func (g GenericGetter) GetOwner(contractAbi, contractAddress string, blockNumber int64) (common.Address, error) {
return g.fetcher.FetchAddress("owner", contractAbi, contractAddress, blockNumber, nil)
}
func (g Getter) GetStoppedStatus(contractAbi, contractAddress string, blockNumber int64) (bool, error) {
func (g GenericGetter) GetStoppedStatus(contractAbi, contractAddress string, blockNumber int64) (bool, error) {
return g.fetcher.FetchBool("stopped", contractAbi, contractAddress, blockNumber, nil)
}
func (g Getter) GetStringName(contractAbi, contractAddress string, blockNumber int64) (string, error) {
func (g GenericGetter) GetStringName(contractAbi, contractAddress string, blockNumber int64) (string, error) {
return g.fetcher.FetchString("name", contractAbi, contractAddress, blockNumber, nil)
}
func (g Getter) GetHashName(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) {
func (g GenericGetter) GetHashName(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) {
return g.fetcher.FetchHash("name", contractAbi, contractAddress, blockNumber, nil)
}
func (g Getter) GetStringSymbol(contractAbi, contractAddress string, blockNumber int64) (string, error) {
func (g GenericGetter) GetStringSymbol(contractAbi, contractAddress string, blockNumber int64) (string, error) {
return g.fetcher.FetchString("symbol", contractAbi, contractAddress, blockNumber, nil)
}
func (g Getter) GetHashSymbol(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) {
func (g GenericGetter) GetHashSymbol(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) {
return g.fetcher.FetchHash("symbol", contractAbi, contractAddress, blockNumber, nil)
}
func (g Getter) GetDecimals(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) {
func (g GenericGetter) GetDecimals(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) {
return g.fetcher.FetchBigInt("decimals", contractAbi, contractAddress, blockNumber, nil)
}
// Method to retrieve the Getter's blockchain
func (g Getter) GetBlockChain() core.BlockChain {
func (g GenericGetter) GetBlockChain() core.BlockChain {
return g.fetcher.BlockChain
}

View File

@ -15,12 +15,14 @@
package every_block_test
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/examples/constants"
"github.com/vulcanize/vulcanizedb/examples/generic/every_block"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
@ -28,7 +30,6 @@ import (
"github.com/vulcanize/vulcanizedb/pkg/geth/client"
rpc2 "github.com/vulcanize/vulcanizedb/pkg/geth/converters/rpc"
"github.com/vulcanize/vulcanizedb/pkg/geth/node"
"math/big"
)
var _ = Describe("every_block Getter", func() {

View File

@ -20,6 +20,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/pkg/core"
)

View File

@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/vulcanize/vulcanizedb/pkg/core"
)

View File

@ -16,21 +16,25 @@ package generic
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
// Retriever is used to iterate over addresses going into or out of a contract
// address in an attempt to generate a list of token holder addresses
type RetrieverInterface interface {
retrieveTransferEventAddresses() ([][2]string, error)
retrieveApprovalEventAddresses() ([][2]string, error)
RetrieveContractAssociatedAddresses() (map[common.Address]bool, error)
type TokenHolderRetrieverInterface interface {
RetrieveTokenHolderAddresses() (map[common.Address]bool, error)
retrieveTokenSenders() ([]string, error)
retrieveTokenReceivers() ([]string, error)
retrieveTokenOwners() ([]string, error)
retrieveTokenSpenders() ([]string, error)
}
type Retriever struct {
type TokenHolderRetriever struct {
Database *postgres.DB
ContractAddress string
}
@ -59,16 +63,18 @@ const (
GetReceiversError = "Error fetching token receivers from contract %s: %s"
GetOwnersError = "Error fetching token owners from contract %s: %s"
GetSpendersError = "Error fetching token spenders from contract %s: %s"
GetMinteesError = "Error fetching token mintees from contract %s: %s"
GetBurnersError = "Error fetching token burners from contract %s: %s"
)
func NewRetriever(db *postgres.DB, address string) Retriever {
return Retriever{
func NewTokenHolderRetriever(db *postgres.DB, address string) TokenHolderRetriever {
return TokenHolderRetriever{
Database: db,
ContractAddress: address,
}
}
func (rt Retriever) retrieveTokenSenders() ([]string, error) {
func (rt TokenHolderRetriever) retrieveTokenSenders() ([]string, error) {
senders := make([]string, 0)
@ -81,10 +87,11 @@ func (rt Retriever) retrieveTokenSenders() ([]string, error) {
if err != nil {
return []string{}, newRetrieverError(err, GetSendersError, rt.ContractAddress)
}
return senders, err
return senders, nil
}
func (rt Retriever) retrieveTokenReceivers() ([]string, error) {
func (rt TokenHolderRetriever) retrieveTokenReceivers() ([]string, error) {
receivers := make([]string, 0)
@ -100,7 +107,41 @@ func (rt Retriever) retrieveTokenReceivers() ([]string, error) {
return receivers, err
}
func (rt Retriever) retrieveTokenOwners() ([]string, error) {
func (rt TokenHolderRetriever) retrieveTokenMintees() ([]string, error) {
mintees := make([]string, 0)
err := rt.Database.DB.Select(
&mintees,
`SELECT mintee FROM token_mints
WHERE token_address = $1`,
rt.ContractAddress,
)
if err != nil {
return []string{}, newRetrieverError(err, GetMinteesError, rt.ContractAddress)
}
return mintees, nil
}
func (rt TokenHolderRetriever) retrieveTokenBurners() ([]string, error) {
burners := make([]string, 0)
err := rt.Database.DB.Select(
&burners,
`SELECT burner FROM token_burns
WHERE token_address = $1`,
rt.ContractAddress,
)
if err != nil {
return []string{}, newRetrieverError(err, GetBurnersError, rt.ContractAddress)
}
return burners, nil
}
func (rt TokenHolderRetriever) retrieveTokenOwners() ([]string, error) {
owners := make([]string, 0)
@ -113,10 +154,11 @@ func (rt Retriever) retrieveTokenOwners() ([]string, error) {
if err != nil {
return []string{}, newRetrieverError(err, GetOwnersError, rt.ContractAddress)
}
return owners, err
return owners, nil
}
func (rt Retriever) retrieveTokenSpenders() ([]string, error) {
func (rt TokenHolderRetriever) retrieveTokenSpenders() ([]string, error) {
spenders := make([]string, 0)
@ -129,10 +171,11 @@ func (rt Retriever) retrieveTokenSpenders() ([]string, error) {
if err != nil {
return []string{}, newRetrieverError(err, GetSpendersError, rt.ContractAddress)
}
return spenders, err
return spenders, nil
}
func (rt Retriever) RetrieveTokenHolderAddresses() (map[common.Address]bool, error) {
func (rt TokenHolderRetriever) RetrieveTokenHolderAddresses() (map[common.Address]bool, error) {
senders, err := rt.retrieveTokenSenders()
if err != nil {
@ -144,6 +187,16 @@ func (rt Retriever) RetrieveTokenHolderAddresses() (map[common.Address]bool, err
return nil, err
}
mintees, err := rt.retrieveTokenMintees()
if err != nil {
return nil, err
}
burners, err := rt.retrieveTokenBurners()
if err != nil {
return nil, err
}
owners, err := rt.retrieveTokenOwners()
if err != nil {
return nil, err
@ -164,6 +217,14 @@ func (rt Retriever) RetrieveTokenHolderAddresses() (map[common.Address]bool, err
contractAddresses[common.HexToAddress(addr)] = true
}
for _, addr := range mintees {
contractAddresses[common.HexToAddress(addr)] = true
}
for _, addr := range burners {
contractAddresses[common.HexToAddress(addr)] = true
}
for _, addr := range owners {
contractAddresses[common.HexToAddress(addr)] = true
}

View File

@ -0,0 +1,78 @@
// 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 mocks
import (
et1 "github.com/vulcanize/vulcanizedb/examples/erc20_watcher/event_triggered"
et2 "github.com/vulcanize/vulcanizedb/examples/generic/event_triggered"
"github.com/vulcanize/vulcanizedb/pkg/core"
)
type MockERC20Converter struct {
WatchedEvents []*core.WatchedEvent
TransfersToConvert []et1.TransferEntity
ApprovalsToConvert []et1.ApprovalEntity
BurnsToConvert []et2.BurnEntity
MintsToConvert []et2.MintEntity
block int64
}
func (mlkc *MockERC20Converter) ToTransferModel(entity *et1.TransferEntity) *et1.TransferModel {
mlkc.TransfersToConvert = append(mlkc.TransfersToConvert, *entity)
return &et1.TransferModel{}
}
func (mlkc *MockERC20Converter) ToTransferEntity(watchedEvent core.WatchedEvent) (*et1.TransferEntity, error) {
mlkc.WatchedEvents = append(mlkc.WatchedEvents, &watchedEvent)
e := &et1.TransferEntity{Block: watchedEvent.BlockNumber}
mlkc.block++
return e, nil
}
func (mlkc *MockERC20Converter) ToApprovalModel(entity *et1.ApprovalEntity) *et1.ApprovalModel {
mlkc.ApprovalsToConvert = append(mlkc.ApprovalsToConvert, *entity)
return &et1.ApprovalModel{}
}
func (mlkc *MockERC20Converter) ToApprovalEntity(watchedEvent core.WatchedEvent) (*et1.ApprovalEntity, error) {
mlkc.WatchedEvents = append(mlkc.WatchedEvents, &watchedEvent)
e := &et1.ApprovalEntity{Block: watchedEvent.BlockNumber}
mlkc.block++
return e, nil
}
func (mlkc *MockERC20Converter) ToBurnEntity(watchedEvent core.WatchedEvent) (*et2.BurnEntity, error) {
mlkc.WatchedEvents = append(mlkc.WatchedEvents, &watchedEvent)
e := &et2.BurnEntity{Block: watchedEvent.BlockNumber}
mlkc.block++
return e, nil
}
func (mlkc *MockERC20Converter) ToBurnModel(entity *et2.BurnEntity) *et2.BurnModel {
mlkc.BurnsToConvert = append(mlkc.BurnsToConvert, *entity)
return &et2.BurnModel{}
}
func (mlkc *MockERC20Converter) ToMintEntity(watchedEvent core.WatchedEvent) (*et2.MintEntity, error) {
mlkc.WatchedEvents = append(mlkc.WatchedEvents, &watchedEvent)
e := &et2.MintEntity{Block: watchedEvent.BlockNumber}
mlkc.block++
return e, nil
}
func (mlkc *MockERC20Converter) ToMintModel(entity *et2.MintEntity) *et2.MintModel {
mlkc.MintsToConvert = append(mlkc.MintsToConvert, *entity)
return &et2.MintModel{}
}

View File

@ -15,7 +15,8 @@
package mocks
import (
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/event_triggered"
et1 "github.com/vulcanize/vulcanizedb/examples/erc20_watcher/event_triggered"
et2 "github.com/vulcanize/vulcanizedb/examples/generic/event_triggered"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/filters"
)
@ -23,6 +24,8 @@ import (
type MockWatchedEventsRepository struct {
watchedTransferEvents []*core.WatchedEvent
watchedApprovalEvents []*core.WatchedEvent
watchedBurnEvents []*core.WatchedEvent
watchedMintEvents []*core.WatchedEvent
Names []string
}
@ -34,6 +37,12 @@ func (mwer *MockWatchedEventsRepository) SetWatchedEvents(watchedEvents []*core.
if event.Name == "Approval" {
mwer.watchedApprovalEvents = append(mwer.watchedApprovalEvents, event)
}
if event.Name == "Burn" {
mwer.watchedBurnEvents = append(mwer.watchedBurnEvents, event)
}
if event.Name == "Mint" {
mwer.watchedMintEvents = append(mwer.watchedMintEvents, event)
}
}
}
@ -50,23 +59,47 @@ func (mwer *MockWatchedEventsRepository) GetWatchedEvents(name string) ([]*core.
// clear watched events once returned so same events are returned for every filter while testing
mwer.watchedApprovalEvents = []*core.WatchedEvent{}
}
if name == "Burn" {
result = mwer.watchedBurnEvents
// clear watched events once returned so same events are returned for every filter while testing
mwer.watchedBurnEvents = []*core.WatchedEvent{}
}
if name == "Mint" {
result = mwer.watchedMintEvents
// clear watched events once returned so same events are returned for every filter while testing
mwer.watchedMintEvents = []*core.WatchedEvent{}
}
return result, nil
}
type MockEventRepo struct {
TransferLogs []event_triggered.TransferModel
ApprovalLogs []event_triggered.ApprovalModel
TransferLogs []et1.TransferModel
ApprovalLogs []et1.ApprovalModel
BurnLogs []et2.BurnModel
MintLogs []et2.MintModel
VulcanizeLogIDs []int64
}
func (molr *MockEventRepo) CreateTransfer(transferModel event_triggered.TransferModel, vulcanizeLogId int64) error {
molr.TransferLogs = append(molr.TransferLogs, transferModel)
func (molr *MockEventRepo) CreateTransfer(transferModel *et1.TransferModel, vulcanizeLogId int64) error {
molr.TransferLogs = append(molr.TransferLogs, *transferModel)
molr.VulcanizeLogIDs = append(molr.VulcanizeLogIDs, vulcanizeLogId)
return nil
}
func (molk *MockEventRepo) CreateApproval(approvalModel event_triggered.ApprovalModel, vulcanizeLogID int64) error {
molk.ApprovalLogs = append(molk.ApprovalLogs, approvalModel)
func (molk *MockEventRepo) CreateApproval(approvalModel *et1.ApprovalModel, vulcanizeLogID int64) error {
molk.ApprovalLogs = append(molk.ApprovalLogs, *approvalModel)
molk.VulcanizeLogIDs = append(molk.VulcanizeLogIDs, vulcanizeLogID)
return nil
}
func (molr *MockEventRepo) CreateBurn(burnModel *et2.BurnModel, vulcanizeLogId int64) error {
molr.BurnLogs = append(molr.BurnLogs, *burnModel)
molr.VulcanizeLogIDs = append(molr.VulcanizeLogIDs, vulcanizeLogId)
return nil
}
func (molk *MockEventRepo) CreateMint(mintModel *et2.MintModel, vulcanizeLogID int64) error {
molk.MintLogs = append(molk.MintLogs, *mintModel)
molk.VulcanizeLogIDs = append(molk.VulcanizeLogIDs, vulcanizeLogID)
return nil
}

View File

@ -17,10 +17,11 @@ package mocks
import (
"errors"
"math/big"
"reflect"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/pkg/core"
"reflect"
)
type Fetcher struct {

View File

@ -18,6 +18,7 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/vulcanize/vulcanizedb/pkg/core"
)

View File

@ -15,8 +15,12 @@
package test_helpers
import (
"math/rand"
"time"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
@ -74,3 +78,52 @@ func CreateBlock(blockNumber int64, repository repositories.BlockRepository) (bl
return blockId
}
func SetupIntegrationDB(db *postgres.DB, logs []core.Log) *postgres.DB {
rand.Seed(time.Now().UnixNano())
db, err := postgres.NewDB(config.Database{
Hostname: "localhost",
Name: "vulcanize_private",
Port: 5432,
}, core.Node{})
Expect(err).NotTo(HaveOccurred())
receiptRepository := repositories.ReceiptRepository{DB: db}
blockRepository := *repositories.NewBlockRepository(db)
blockNumber := rand.Int63()
blockId := CreateBlock(blockNumber, blockRepository)
receipt := core.Receipt{
Logs: logs,
}
receipts := []core.Receipt{receipt}
err = receiptRepository.CreateReceiptsAndLogs(blockId, receipts)
Expect(err).NotTo(HaveOccurred())
var vulcanizeLogIds []int64
err = db.Select(&vulcanizeLogIds, `SELECT id FROM logs`)
Expect(err).NotTo(HaveOccurred())
return db
}
func TearDownIntegrationDB(db *postgres.DB) *postgres.DB {
_, err := db.Exec(`DELETE FROM token_transfers`)
Expect(err).NotTo(HaveOccurred())
_, err = db.Exec(`DELETE FROM token_approvals`)
Expect(err).NotTo(HaveOccurred())
_, err = db.Exec(`DELETE FROM log_filters`)
Expect(err).NotTo(HaveOccurred())
_, err = db.Exec(`DELETE FROM logs`)
Expect(err).NotTo(HaveOccurred())
return db
}

View File

@ -8,6 +8,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/geth"
"github.com/vulcanize/vulcanizedb/pkg/geth/client"

View File

@ -5,6 +5,7 @@ import (
"github.com/ethereum/go-ethereum/rpc"
. "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/geth"

View File

@ -1,10 +1,10 @@
package integration_test
import (
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestIntegrationTest(t *testing.T) {

View File

@ -2,10 +2,10 @@ package test_config
import (
"log"
"os"
"github.com/spf13/viper"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"

View File

@ -2,12 +2,9 @@ package utils
import (
"log"
"path/filepath"
"math/big"
"os"
"path/filepath"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"

View File

@ -898,132 +898,132 @@ var testVectors = []struct {
r, s string
ok bool
}{
/*
* All of these tests are disabled since they are for P224, not sec256k1.
* they are left here as an example of test vectors for when some *real*
* vectors may be found.
* - oga@conformal.com
{
"09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd",
"9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40",
"03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed",
"81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1",
"96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5",
false,
},
{
"96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37",
"851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8",
"205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2",
"4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0",
"e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12",
false,
},
{
"86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e",
"ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc",
"c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984",
"de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9",
"745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd",
true,
},
{
"4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d",
"cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8",
"a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a",
"67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836",
"1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020",
false,
},
{
"bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e",
"6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855",
"27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84",
"e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f",
"1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9",
false,
},
{
"7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43",
"9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1",
"8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066",
"6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54",
"8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57",
false,
},
{
"cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601",
"a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4",
"e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5",
"387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1",
"4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4",
false,
},
{
"26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866",
"9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d",
"15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c",
"929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0",
"59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872",
true,
},
{
"1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e",
"d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b",
"631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f",
"65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129",
"bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a",
false,
},
{
"919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b",
"269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574",
"baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57",
"cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008",
"40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40",
false,
},
{
"6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f",
"6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd",
"26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b",
"9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad",
"8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97",
true,
},
{
"bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566",
"14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40",
"b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803",
"4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145",
"452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8",
false,
},
{
"0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770",
"d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac",
"76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb",
"bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca",
"9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e",
false,
},
{
"5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92",
"7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6",
"44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9",
"084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8",
"079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3",
false,
},
{
"1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845",
"31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493",
"a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4",
"bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c",
"ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0",
false,
},
*/
/*
* All of these tests are disabled since they are for P224, not sec256k1.
* they are left here as an example of test vectors for when some *real*
* vectors may be found.
* - oga@conformal.com
{
"09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd",
"9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40",
"03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed",
"81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1",
"96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5",
false,
},
{
"96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37",
"851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8",
"205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2",
"4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0",
"e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12",
false,
},
{
"86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e",
"ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc",
"c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984",
"de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9",
"745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd",
true,
},
{
"4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d",
"cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8",
"a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a",
"67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836",
"1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020",
false,
},
{
"bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e",
"6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855",
"27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84",
"e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f",
"1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9",
false,
},
{
"7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43",
"9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1",
"8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066",
"6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54",
"8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57",
false,
},
{
"cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601",
"a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4",
"e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5",
"387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1",
"4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4",
false,
},
{
"26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866",
"9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d",
"15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c",
"929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0",
"59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872",
true,
},
{
"1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e",
"d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b",
"631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f",
"65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129",
"bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a",
false,
},
{
"919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b",
"269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574",
"baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57",
"cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008",
"40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40",
false,
},
{
"6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f",
"6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd",
"26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b",
"9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad",
"8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97",
true,
},
{
"bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566",
"14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40",
"b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803",
"4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145",
"452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8",
false,
},
{
"0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770",
"d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac",
"76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb",
"bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca",
"9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e",
false,
},
{
"5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92",
"7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6",
"44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9",
"084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8",
"079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3",
false,
},
{
"1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845",
"31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493",
"a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4",
"bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c",
"ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0",
false,
},
*/
}
func TestVectors(t *testing.T) {