Handle events

- Adds interfaces for developers to build handlers that update data in
response to log events
- Resolves #29
This commit is contained in:
Matt Krump
2018-03-05 10:01:50 -06:00
parent ed907535e3
commit 06f78e0083
163 changed files with 586 additions and 22397 deletions
-73
View File
@@ -1,79 +1,6 @@
package config
import (
"os"
"fmt"
"path/filepath"
"path"
"runtime"
"errors"
"net/url"
"github.com/BurntSushi/toml"
)
type Config struct {
Database Database
Client Client
}
var NewErrConfigFileNotFound = func(environment string) error {
return errors.New(fmt.Sprintf("No configuration found for environment: %v", environment))
}
var NewErrBadConnectionString = func(connectionString string) error {
return errors.New(fmt.Sprintf("connection string is invalid: %v", connectionString))
}
func NewConfig(environment string) (Config, error) {
filenameWithExtension := fmt.Sprintf("%s.toml", environment)
absolutePath := filepath.Join(ProjectRoot(), "environments", filenameWithExtension)
config, err := parseConfigFile(absolutePath)
if err != nil {
return Config{}, NewErrConfigFileNotFound(environment)
} else {
if !filepath.IsAbs(config.Client.IPCPath) && !isUrl(config.Client.IPCPath) {
config.Client.IPCPath = filepath.Join(ProjectRoot(), config.Client.IPCPath)
}
return config, nil
}
}
func ProjectRoot() string {
var _, filename, _, _ = runtime.Caller(0)
return path.Join(path.Dir(filename), "..", "..")
}
func isUrl(s string) bool {
_, err := url.ParseRequestURI(s)
if err == nil {
return true
}
return false
}
func fileExists(s string) bool {
_, err := os.Stat(s)
if err == nil {
return true
}
return false
}
func parseConfigFile(filePath string) (Config, error) {
var cfg Config
if !isUrl(filePath) && !fileExists(filePath) {
return Config{}, NewErrBadConnectionString(filePath)
} else {
_, err := toml.DecodeFile(filePath, &cfg)
if err != nil {
return Config{}, err
}
return cfg, nil
}
}
+10 -27
View File
@@ -1,41 +1,24 @@
package config_test
import (
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
cfg "github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/spf13/viper"
)
var _ = Describe("Loading the config", func() {
It("reads the private config using the environment", func() {
privateConfig, err := cfg.NewConfig("private")
testConfig := viper.New()
testConfig.SetConfigName("private")
testConfig.AddConfigPath("$GOPATH/src/github.com/vulcanize/vulcanizedb/environments/")
err := testConfig.ReadInConfig()
Expect(viper.Get("client.ipcpath")).To(BeNil())
Expect(err).To(BeNil())
Expect(privateConfig.Database.Hostname).To(Equal("localhost"))
Expect(privateConfig.Database.Name).To(Equal("vulcanize_private"))
Expect(privateConfig.Database.Port).To(Equal(5432))
expandedPath := filepath.Join(cfg.ProjectRoot(), "test_data_dir/geth.ipc")
Expect(privateConfig.Client.IPCPath).To(Equal(expandedPath))
})
It("returns an error when there is no matching config file", func() {
config, err := cfg.NewConfig("bad-config")
Expect(config).To(Equal(cfg.Config{}))
Expect(err).NotTo(BeNil())
})
It("reads the infura config using the environment", func() {
infuraConfig, err := cfg.NewConfig("infura")
Expect(err).To(BeNil())
Expect(infuraConfig.Database.Hostname).To(Equal("localhost"))
Expect(infuraConfig.Database.Name).To(Equal("vulcanize_private"))
Expect(infuraConfig.Database.Port).To(Equal(5432))
Expect(infuraConfig.Client.IPCPath).To(Equal("https://mainnet.infura.io/J5Vd2fRtGsw0zZ0Ov3BL"))
Expect(testConfig.Get("database.hostname")).To(Equal("localhost"))
Expect(testConfig.Get("database.name")).To(Equal("vulcanize_private"))
Expect(testConfig.Get("database.port")).To(Equal(int64(5432)))
Expect(testConfig.Get("client.ipcpath")).To(Equal("test_data_dir/geth.ipc"))
})
})
+2 -3
View File
@@ -30,11 +30,10 @@ func template() string {
func transactionToString(transaction *core.Transaction) string {
if transaction == nil {
return "NONE"
} else {
return fmt.Sprintf(`Hash: %s
}
return fmt.Sprintf(`Hash: %s
To: %s
From: %s`, transaction.Hash, transaction.To, transaction.From)
}
}
func attributesString(summary ContractSummary) string {
+4 -6
View File
@@ -4,7 +4,7 @@ import (
"math/big"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
)
type ContractSummary struct {
@@ -17,13 +17,12 @@ type ContractSummary struct {
blockChain core.Blockchain
}
func NewSummary(blockchain core.Blockchain, contractRepository repositories.ContractRepository, contractHash string, blockNumber *big.Int) (ContractSummary, error) {
func NewSummary(blockchain core.Blockchain, contractRepository datastore.ContractRepository, contractHash string, blockNumber *big.Int) (ContractSummary, error) {
contract, err := contractRepository.GetContract(contractHash)
if err != nil {
return ContractSummary{}, err
} else {
return newContractSummary(blockchain, contract, blockNumber), nil
}
return newContractSummary(blockchain, contract, blockNumber), nil
}
func (contractSummary ContractSummary) GetStateAttribute(attributeName string) interface{} {
@@ -48,7 +47,6 @@ func newContractSummary(blockchain core.Blockchain, contract core.Contract, bloc
func lastTransaction(contract core.Contract) *core.Transaction {
if len(contract.Transactions) > 0 {
return &contract.Transactions[0]
} else {
return nil
}
return nil
}
+4 -3
View File
@@ -7,12 +7,12 @@ import (
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/contract_summary"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/inmemory"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/repositories/inmemory"
)
func NewCurrentContractSummary(blockchain core.Blockchain, contractRepository repositories.ContractRepository, contractHash string) (contract_summary.ContractSummary, error) {
func NewCurrentContractSummary(blockchain core.Blockchain, contractRepository datastore.ContractRepository, contractHash string) (contract_summary.ContractSummary, error) {
return contract_summary.NewSummary(blockchain, contractRepository, contractHash, nil)
}
@@ -143,6 +143,7 @@ var _ = Describe("The contract summary", func() {
},
))
})
})
})
+7 -3
View File
@@ -3,10 +3,14 @@ package core
import "math/big"
type Blockchain interface {
GetAttribute(contract Contract, attributeName string, blockNumber *big.Int) (interface{}, error)
GetAttributes(contract Contract) (ContractAttributes, error)
GetBlockByNumber(blockNumber int64) Block
GetLogs(contract Contract, startingBlockNumber *big.Int, endingBlockNumber *big.Int) ([]Log, error)
LastBlock() *big.Int
Node() Node
GetAttributes(contract Contract) (ContractAttributes, error)
GetAttribute(contract Contract, attributeName string, blockNumber *big.Int) (interface{}, error)
GetLogs(contract Contract, startingBlockNumber *big.Int, endingBlockNumber *big.Int) ([]Log, error)
}
type ContractDataFetcher interface {
FetchContractData(abiJSON string, address string, method string, methodArg interface{}, result interface{}, blockNumber int64) error
}
+2 -2
View File
@@ -2,7 +2,7 @@ package core
type Node struct {
GenesisBlock string
NetworkId float64
Id string
NetworkID float64
ID string
ClientName string
}
+11 -10
View File
@@ -1,14 +1,15 @@
package core
type WatchedEvent struct {
Name string `json:"name"` // name
BlockNumber int64 `json:"block_number" db:"block_number"` // block_number
Address string `json:"address"` // address
TxHash string `json:"tx_hash" db:"tx_hash"` // tx_hash
Index int64 `json:"index"` // index
Topic0 string `json:"topic0"` // topic0
Topic1 string `json:"topic1"` // topic1
Topic2 string `json:"topic2"` // topic2
Topic3 string `json:"topic3"` // topic3
Data string `json:"data"` // data
LogID int64 `json:"log_id" db:"id"`
Name string `json:"name"`
BlockNumber int64 `json:"block_number" db:"block_number"`
Address string `json:"address"`
TxHash string `json:"tx_hash" db:"tx_hash"`
Index int64 `json:"index"`
Topic0 string `json:"topic0"`
Topic1 string `json:"topic1"`
Topic2 string `json:"topic2"`
Topic3 string `json:"topic3"`
Data string `json:"data"`
}
@@ -2,7 +2,7 @@ package inmemory
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
)
type BlockRepository struct {
@@ -23,7 +23,7 @@ func (blockRepository *BlockRepository) GetBlock(blockNumber int64) (core.Block,
if block, ok := blockRepository.blocks[blockNumber]; ok {
return block, nil
}
return core.Block{}, repositories.ErrBlockDoesNotExist(blockNumber)
return core.Block{}, datastore.ErrBlockDoesNotExist(blockNumber)
}
func (blockRepository *BlockRepository) MissingBlockNumbers(startingBlockNumber int64, endingBlockNumber int64) []int64 {
@@ -2,7 +2,7 @@ package inmemory
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
)
type ContractRepostiory struct {
@@ -17,7 +17,7 @@ func (contractRepository *ContractRepostiory) ContractExists(contractHash string
func (contractRepository *ContractRepostiory) GetContract(contractHash string) (core.Contract, error) {
contract, ok := contractRepository.contracts[contractHash]
if !ok {
return core.Contract{}, repositories.ErrContractDoesNotExist(contractHash)
return core.Contract{}, datastore.ErrContractDoesNotExist(contractHash)
}
for _, block := range contractRepository.blocks {
for _, transaction := range block.Transactions {
@@ -4,15 +4,15 @@ import (
"errors"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
_ "github.com/lib/pq" //postgres driver
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
)
type DB struct {
*sqlx.DB
node core.Node
nodeId int64
Node core.Node
NodeID int64
}
var (
@@ -28,7 +28,7 @@ func NewDB(databaseConfig config.Database, node core.Node) (*DB, error) {
if err != nil {
return &DB{}, ErrDBConnectionFailed
}
pg := DB{DB: db, node: node}
pg := DB{DB: db, Node: node}
err = pg.CreateNode(&node)
if err != nil {
return &DB{}, ErrUnableToSetNode
@@ -48,10 +48,10 @@ func (db *DB) CreateNode(node *core.Node) error {
node_id = $3,
client_name = $4
RETURNING id`,
node.GenesisBlock, node.NetworkId, node.Id, node.ClientName).Scan(&nodeId)
node.GenesisBlock, node.NetworkID, node.ID, node.ClientName).Scan(&nodeId)
if err != nil {
return ErrUnableToSetNode
}
db.nodeId = nodeId
db.NodeID = nodeId
return nil
}
@@ -15,7 +15,9 @@ import (
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/test_config"
)
func init() {
@@ -23,24 +25,14 @@ func init() {
}
var _ = Describe("Postgres DB", func() {
var db *postgres.DB
var sqlxdb *sqlx.DB
It("connects to the database", func() {
cfg, _ := config.NewConfig("private")
pgConfig := config.DbConnectionString(cfg.Database)
db, err := sqlx.Connect("postgres", pgConfig)
var err error
pgConfig := config.DbConnectionString(test_config.DBConfig)
sqlxdb, err = sqlx.Connect("postgres", pgConfig)
Expect(err).Should(BeNil())
Expect(db).ShouldNot(BeNil())
})
BeforeEach(func() {
node := core.Node{
GenesisBlock: "GENESIS",
NetworkId: 1,
Id: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
}
db = postgres.NewTestDB(node)
Expect(sqlxdb).ShouldNot(BeNil())
})
It("serializes big.Int to db", func() {
@@ -51,9 +43,9 @@ var _ = Describe("Postgres DB", func() {
// sized int, so use string representation of big.Int
// and cast on insert
cfg, _ := config.NewConfig("private")
pgConfig := config.DbConnectionString(cfg.Database)
db, err := sqlx.Connect("postgres", pgConfig)
pgConnectString := config.DbConnectionString(test_config.DBConfig)
db, err := sqlx.Connect("postgres", pgConnectString)
Expect(err).NotTo(HaveOccurred())
bi := new(big.Int)
bi.SetString("34940183920000000000", 10)
@@ -87,10 +79,9 @@ var _ = Describe("Postgres DB", func() {
Nonce: badNonce,
Transactions: []core.Transaction{},
}
cfg, _ := config.NewConfig("private")
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
db, _ := postgres.NewDB(cfg.Database, node)
blocksRepository := postgres.BlockRepository{DB: db}
node := core.Node{GenesisBlock: "GENESIS", NetworkID: 1, ID: "x123", ClientName: "geth"}
db := test_config.NewTestDB(node)
blocksRepository := repositories.BlockRepository{DB: db}
err1 := blocksRepository.CreateOrUpdateBlock(badBlock)
savedBlock, err2 := blocksRepository.GetBlock(123)
@@ -102,16 +93,15 @@ var _ = Describe("Postgres DB", func() {
It("throws error when can't connect to the database", func() {
invalidDatabase := config.Database{}
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
node := core.Node{GenesisBlock: "GENESIS", NetworkID: 1, ID: "x123", ClientName: "geth"}
_, err := postgres.NewDB(invalidDatabase, node)
Expect(err).To(Equal(postgres.ErrDBConnectionFailed))
})
It("throws error when can't create node", func() {
cfg, _ := config.NewConfig("private")
badHash := fmt.Sprintf("x %s", strings.Repeat("1", 100))
node := core.Node{GenesisBlock: badHash, NetworkId: 1, Id: "x123", ClientName: "geth"}
_, err := postgres.NewDB(cfg.Database, node)
node := core.Node{GenesisBlock: badHash, NetworkID: 1, ID: "x123", ClientName: "geth"}
_, err := postgres.NewDB(test_config.DBConfig, node)
Expect(err).To(Equal(postgres.ErrUnableToSetNode))
})
@@ -123,10 +113,9 @@ var _ = Describe("Postgres DB", func() {
BlockNumber: 1,
TxHash: badTxHash,
}
cfg, _ := config.NewConfig("private")
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
db, _ := postgres.NewDB(cfg.Database, node)
logRepository := postgres.LogRepository{DB: db}
node := core.Node{GenesisBlock: "GENESIS", NetworkID: 1, ID: "x123", ClientName: "geth"}
db, _ := postgres.NewDB(test_config.DBConfig, node)
logRepository := repositories.LogRepository{DB: db}
err := logRepository.CreateLogs([]core.Log{badLog})
savedBlock := logRepository.GetLogs("x123", 1)
@@ -143,10 +132,9 @@ var _ = Describe("Postgres DB", func() {
Number: 123,
Transactions: []core.Transaction{badTransaction},
}
cfg, _ := config.NewConfig("private")
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
db, _ := postgres.NewDB(cfg.Database, node)
blockRepository := postgres.BlockRepository{DB: db}
node := core.Node{GenesisBlock: "GENESIS", NetworkID: 1, ID: "x123", ClientName: "geth"}
db, _ := postgres.NewDB(test_config.DBConfig, node)
blockRepository := repositories.BlockRepository{DB: db}
err1 := blockRepository.CreateOrUpdateBlock(block)
savedBlock, err2 := blockRepository.GetBlock(123)
@@ -1,15 +1,15 @@
package postgres
package repositories
import (
"context"
"database/sql"
"fmt"
"log"
"github.com/jmoiron/sqlx"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
const (
@@ -17,7 +17,7 @@ const (
)
type BlockRepository struct {
*DB
*postgres.DB
}
func (blockRepository BlockRepository) SetBlocksStatus(chainHead int64) {
@@ -79,12 +79,12 @@ func (blockRepository BlockRepository) GetBlock(blockNumber int64) (core.Block,
reward,
uncles_reward
FROM blocks
WHERE node_id = $1 AND number = $2`, blockRepository.nodeId, blockNumber)
WHERE node_id = $1 AND number = $2`, blockRepository.NodeID, blockNumber)
savedBlock, err := blockRepository.loadBlock(blockRows)
if err != nil {
switch err {
case sql.ErrNoRows:
return core.Block{}, repositories.ErrBlockDoesNotExist(blockNumber)
return core.Block{}, datastore.ErrBlockDoesNotExist(blockNumber)
default:
return savedBlock, err
}
@@ -100,16 +100,16 @@ func (blockRepository BlockRepository) insertBlock(block core.Block) error {
(node_id, number, gaslimit, gasused, time, difficulty, hash, nonce, parenthash, size, uncle_hash, is_final, miner, extra_data, reward, uncles_reward)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
RETURNING id `,
blockRepository.nodeId, block.Number, block.GasLimit, block.GasUsed, block.Time, block.Difficulty, block.Hash, block.Nonce, block.ParentHash, block.Size, block.UncleHash, block.IsFinal, block.Miner, block.ExtraData, block.Reward, block.UnclesReward).
blockRepository.NodeID, block.Number, block.GasLimit, block.GasUsed, block.Time, block.Difficulty, block.Hash, block.Nonce, block.ParentHash, block.Size, block.UncleHash, block.IsFinal, block.Miner, block.ExtraData, block.Reward, block.UnclesReward).
Scan(&blockId)
if err != nil {
tx.Rollback()
return ErrDBInsertFailed
return postgres.ErrDBInsertFailed
}
err = blockRepository.createTransactions(tx, blockId, block.Transactions)
if err != nil {
tx.Rollback()
return ErrDBInsertFailed
return postgres.ErrDBInsertFailed
}
tx.Commit()
return nil
@@ -191,7 +191,7 @@ func (blockRepository BlockRepository) getBlockHash(block core.Block) (string, b
`SELECT hash
FROM blocks
WHERE number = $1 AND node_id = $2`,
block.Number, blockRepository.nodeId)
block.Number, blockRepository.NodeID)
return retrievedBlockHash, blockExists(retrievedBlockHash)
}
@@ -204,7 +204,7 @@ func (blockRepository BlockRepository) createLogs(tx *sql.Tx, logs []core.Log, r
tlog.BlockNumber, tlog.Address, tlog.TxHash, tlog.Index, tlog.Topics[0], tlog.Topics[1], tlog.Topics[2], tlog.Topics[3], tlog.Data, receiptId,
)
if err != nil {
return ErrDBInsertFailed
return postgres.ErrDBInsertFailed
}
}
return nil
@@ -219,9 +219,9 @@ func (blockRepository BlockRepository) removeBlock(blockNumber int64) error {
`DELETE FROM
blocks
WHERE number=$1 AND node_id=$2`,
blockNumber, blockRepository.nodeId)
blockNumber, blockRepository.NodeID)
if err != nil {
return ErrDBDeleteFailed
return postgres.ErrDBDeleteFailed
}
return nil
}
@@ -261,7 +261,6 @@ func (blockRepository BlockRepository) LoadTransactions(transactionRows *sqlx.Ro
var transaction core.Transaction
err := transactionRows.StructScan(&transaction)
if err != nil {
fmt.Println(err)
log.Fatal(err)
}
transactions = append(transactions, transaction)
@@ -1,4 +1,4 @@
package postgres_test
package repositories_test
import (
"math/big"
@@ -7,22 +7,24 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("Saving blocks", func() {
var db *postgres.DB
var blockRepository repositories.BlockRepository
var blockRepository datastore.BlockRepository
BeforeEach(func() {
node := core.Node{
GenesisBlock: "GENESIS",
NetworkId: 1,
Id: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
NetworkID: 1,
ID: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
}
db = postgres.NewTestDB(node)
blockRepository = postgres.BlockRepository{DB: db}
db = test_config.NewTestDB(node)
blockRepository = repositories.BlockRepository{DB: db}
})
@@ -33,12 +35,12 @@ var _ = Describe("Saving blocks", func() {
blockRepository.CreateOrUpdateBlock(block)
nodeTwo := core.Node{
GenesisBlock: "0x456",
NetworkId: 1,
Id: "x123456",
NetworkID: 1,
ID: "x123456",
ClientName: "Geth",
}
dbTwo := postgres.NewTestDB(nodeTwo)
repositoryTwo := postgres.BlockRepository{DB: dbTwo}
dbTwo := test_config.NewTestDB(nodeTwo)
repositoryTwo := repositories.BlockRepository{DB: dbTwo}
_, err := repositoryTwo.GetBlock(123)
Expect(err).To(HaveOccurred())
@@ -161,10 +163,10 @@ var _ = Describe("Saving blocks", func() {
blockRepository.CreateOrUpdateBlock(blockOne)
nodeTwo := core.Node{
GenesisBlock: "0x456",
NetworkId: 1,
NetworkID: 1,
}
dbTwo := postgres.NewTestDB(nodeTwo)
repositoryTwo := postgres.BlockRepository{DB: dbTwo}
dbTwo := test_config.NewTestDB(nodeTwo)
repositoryTwo := repositories.BlockRepository{DB: dbTwo}
blockRepository.CreateOrUpdateBlock(blockOne)
repositoryTwo.CreateOrUpdateBlock(blockTwo)
@@ -283,6 +285,5 @@ var _ = Describe("Saving blocks", func() {
Expect(err).ToNot(HaveOccurred())
Expect(blockTwo.IsFinal).To(BeFalse())
})
})
})
@@ -1,14 +1,15 @@
package postgres
package repositories
import (
"database/sql"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type ContractRepository struct {
*DB
*postgres.DB
}
func (contractRepository ContractRepository) CreateContract(contract core.Contract) error {
@@ -25,7 +26,7 @@ func (contractRepository ContractRepository) CreateContract(contract core.Contra
SET contract_hash = $1, contract_abi = $2
`, contract.Hash, abiToInsert)
if err != nil {
return ErrDBInsertFailed
return postgres.ErrDBInsertFailed
}
return nil
}
@@ -47,7 +48,7 @@ func (contractRepository ContractRepository) GetContract(contractHash string) (c
`SELECT contract_hash, contract_abi FROM watched_contracts WHERE contract_hash=$1`, contractHash)
err := contract.Scan(&hash, &abi)
if err == sql.ErrNoRows {
return core.Contract{}, repositories.ErrContractDoesNotExist(contractHash)
return core.Contract{}, datastore.ErrContractDoesNotExist(contractHash)
}
savedContract := contractRepository.addTransactions(core.Contract{Hash: hash, Abi: abi})
return savedContract, nil
@@ -1,4 +1,4 @@
package postgres_test
package repositories_test
import (
"sort"
@@ -6,24 +6,26 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("Creating contracts", func() {
var db *postgres.DB
var contractRepository repositories.ContractRepository
var contractRepository datastore.ContractRepository
var node core.Node
BeforeEach(func() {
node = core.Node{
GenesisBlock: "GENESIS",
NetworkId: 1,
Id: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
NetworkID: 1,
ID: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
}
db = postgres.NewTestDB(node)
contractRepository = postgres.ContractRepository{DB: db}
db = test_config.NewTestDB(node)
contractRepository = repositories.ContractRepository{DB: db}
})
It("returns the contract when it exists", func() {
@@ -50,8 +52,8 @@ var _ = Describe("Creating contracts", func() {
})
It("returns transactions 'To' a contract", func() {
var blockRepository repositories.BlockRepository
blockRepository = postgres.BlockRepository{DB: db}
var blockRepository datastore.BlockRepository
blockRepository = repositories.BlockRepository{DB: db}
block := core.Block{
Number: 123,
Transactions: []core.Transaction{
@@ -1,4 +1,4 @@
package postgres
package repositories
import (
"database/sql"
@@ -6,12 +6,13 @@ import (
"encoding/json"
"errors"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/filters"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
)
type FilterRepository struct {
*DB
*postgres.DB
}
func (filterRepository FilterRepository) CreateFilter(query filters.LogFilter) error {
@@ -41,7 +42,7 @@ func (filterRepository FilterRepository) GetFilter(name string) (filters.LogFilt
if err != nil {
switch err {
case sql.ErrNoRows:
return filters.LogFilter{}, repositories.ErrFilterDoesNotExist(name)
return filters.LogFilter{}, datastore.ErrFilterDoesNotExist(name)
default:
return filters.LogFilter{}, err
}
@@ -57,9 +58,7 @@ func (t *DBTopics) Scan(src interface{}) error {
if !ok {
return error(errors.New("scan source was not []byte"))
}
json.Unmarshal(asBytes, &t)
return nil
return json.Unmarshal(asBytes, &t)
}
type DBLogFilter struct {
@@ -1,27 +1,29 @@
package postgres_test
package repositories_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/pkg/filters"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("Log Filters Repository", func() {
var db *postgres.DB
var filterRepository repositories.FilterRepository
var filterRepository datastore.FilterRepository
var node core.Node
BeforeEach(func() {
node = core.Node{
GenesisBlock: "GENESIS",
NetworkId: 1,
Id: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
NetworkID: 1,
ID: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
}
db = postgres.NewTestDB(node)
filterRepository = postgres.FilterRepository{DB: db}
db = test_config.NewTestDB(node)
filterRepository = repositories.FilterRepository{DB: db}
})
Describe("LogFilter", func() {
@@ -63,7 +65,7 @@ var _ = Describe("Log Filters Repository", func() {
It("gets a log filter", func() {
logFilter1 := filters.LogFilter{
expectedLogFilter1 := filters.LogFilter{
Name: "TestFilter1",
FromBlock: 1,
ToBlock: 2,
@@ -75,9 +77,9 @@ var _ = Describe("Log Filters Repository", func() {
"",
},
}
err := filterRepository.CreateFilter(logFilter1)
err := filterRepository.CreateFilter(expectedLogFilter1)
Expect(err).ToNot(HaveOccurred())
logFilter2 := filters.LogFilter{
expectedLogFilter2 := filters.LogFilter{
Name: "TestFilter2",
FromBlock: 10,
ToBlock: 20,
@@ -89,20 +91,20 @@ var _ = Describe("Log Filters Repository", func() {
"",
},
}
err = filterRepository.CreateFilter(logFilter2)
err = filterRepository.CreateFilter(expectedLogFilter2)
Expect(err).ToNot(HaveOccurred())
logFilter1, err = filterRepository.GetFilter("TestFilter1")
logFilter1, err := filterRepository.GetFilter("TestFilter1")
Expect(err).ToNot(HaveOccurred())
Expect(logFilter1).To(Equal(logFilter1))
logFilter1, err = filterRepository.GetFilter("TestFilter1")
Expect(logFilter1).To(Equal(expectedLogFilter1))
logFilter2, err := filterRepository.GetFilter("TestFilter2")
Expect(err).ToNot(HaveOccurred())
Expect(logFilter2).To(Equal(logFilter2))
Expect(logFilter2).To(Equal(expectedLogFilter2))
})
It("returns ErrFilterDoesNotExist error when log does not exist", func() {
_, err := filterRepository.GetFilter("TestFilter1")
Expect(err).To(Equal(repositories.ErrFilterDoesNotExist("TestFilter1")))
Expect(err).To(Equal(datastore.ErrFilterDoesNotExist("TestFilter1")))
})
})
})
@@ -1,4 +1,4 @@
package postgres
package repositories
import (
"context"
@@ -6,10 +6,11 @@ import (
"database/sql"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type LogRepository struct {
*DB
*postgres.DB
}
func (logRepository LogRepository) CreateLogs(lgs []core.Log) error {
@@ -23,7 +24,7 @@ func (logRepository LogRepository) CreateLogs(lgs []core.Log) error {
)
if err != nil {
tx.Rollback()
return ErrDBInsertFailed
return postgres.ErrDBInsertFailed
}
}
tx.Commit()
@@ -1,4 +1,4 @@
package postgres_test
package repositories_test
import (
"sort"
@@ -6,23 +6,25 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("Logs Repository", func() {
var db *postgres.DB
var logsRepository repositories.LogRepository
var logsRepository datastore.LogRepository
var node core.Node
BeforeEach(func() {
node = core.Node{
GenesisBlock: "GENESIS",
NetworkId: 1,
Id: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
NetworkID: 1,
ID: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
}
db = postgres.NewTestDB(node)
logsRepository = postgres.LogRepository{DB: db}
db = test_config.NewTestDB(node)
logsRepository = repositories.LogRepository{DB: db}
})
Describe("Saving logs", func() {
@@ -115,8 +117,8 @@ var _ = Describe("Logs Repository", func() {
})
It("saves the logs attached to a receipt", func() {
var blockRepository repositories.BlockRepository
blockRepository = postgres.BlockRepository{DB: db}
var blockRepository datastore.BlockRepository
blockRepository = repositories.BlockRepository{DB: db}
logs := []core.Log{{
Address: "0x8a4774fe82c63484afef97ca8d89a6ea5e21f973",
@@ -176,6 +178,5 @@ var _ = Describe("Logs Repository", func() {
expected := logs[1:]
Expect(retrievedLogs).To(Equal(expected))
})
})
})
@@ -1,14 +1,15 @@
package postgres
package repositories
import (
"database/sql"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type ReceiptRepository struct {
*DB
*postgres.DB
}
func (receiptRepository ReceiptRepository) GetReceipt(txHash string) (core.Receipt, error) {
@@ -25,7 +26,7 @@ func (receiptRepository ReceiptRepository) GetReceipt(txHash string) (core.Recei
if err != nil {
switch err {
case sql.ErrNoRows:
return core.Receipt{}, repositories.ErrReceiptDoesNotExist(txHash)
return core.Receipt{}, datastore.ErrReceiptDoesNotExist(txHash)
default:
return core.Receipt{}, err
}
@@ -1,33 +1,35 @@
package postgres_test
package repositories_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ bool = Describe("Logs Repository", func() {
var receiptRepository repositories.ReceiptRepository
var receiptRepository datastore.ReceiptRepository
var db *postgres.DB
var node core.Node
BeforeEach(func() {
node = core.Node{
GenesisBlock: "GENESIS",
NetworkId: 1,
Id: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
NetworkID: 1,
ID: "b6f90c0fdd8ec9607aed8ee45c69322e47b7063f0bfb7a29c8ecafab24d0a22d24dd2329b5ee6ed4125a03cb14e57fd584e67f9e53e6c631055cbbd82f080845",
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
}
db = postgres.NewTestDB(node)
receiptRepository = postgres.ReceiptRepository{DB: db}
db = test_config.NewTestDB(node)
receiptRepository = repositories.ReceiptRepository{DB: db}
})
Describe("Saving receipts", func() {
It("returns the receipt when it exists", func() {
var blockRepository repositories.BlockRepository
db := postgres.NewTestDB(node)
blockRepository = postgres.BlockRepository{DB: db}
var blockRepository datastore.BlockRepository
db := test_config.NewTestDB(node)
blockRepository = repositories.BlockRepository{DB: db}
expected := core.Receipt{
ContractAddress: "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
CumulativeGasUsed: 7996119,
@@ -64,9 +66,9 @@ var _ bool = Describe("Logs Repository", func() {
})
It("still saves receipts without logs", func() {
var blockRepository repositories.BlockRepository
db := postgres.NewTestDB(node)
blockRepository = postgres.BlockRepository{DB: db}
var blockRepository datastore.BlockRepository
db := test_config.NewTestDB(node)
blockRepository = repositories.BlockRepository{DB: db}
receipt := core.Receipt{
TxHash: "0x002c4799161d809b23f67884eb6598c9df5894929fe1a9ead97ca175d360f547",
}
@@ -1,4 +1,4 @@
package graphql_server_test
package repositories_test
import (
"testing"
@@ -7,7 +7,7 @@ import (
. "github.com/onsi/gomega"
)
func TestGraphqlServer(t *testing.T) {
func TestRepositories(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "GraphqlServer Suite")
RunSpecs(t, "Repositories Suite")
}
@@ -1,15 +1,16 @@
package postgres
package repositories
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
)
type WatchedEventRepository struct {
*DB
*postgres.DB
}
func (watchedEventRepository WatchedEventRepository) GetWatchedEvents(name string) ([]*core.WatchedEvent, error) {
rows, err := watchedEventRepository.DB.Queryx(`SELECT name, block_number, address, tx_hash, index, topic0, topic1, topic2, topic3, data FROM watched_event_logs where name=$1`, name)
rows, err := watchedEventRepository.DB.Queryx(`SELECT id, name, block_number, address, tx_hash, index, topic0, topic1, topic2, topic3, data FROM watched_event_logs where name=$1`, name)
if err != nil {
return nil, err
}
@@ -18,7 +19,7 @@ func (watchedEventRepository WatchedEventRepository) GetWatchedEvents(name strin
lgs := make([]*core.WatchedEvent, 0)
for rows.Next() {
lg := new(core.WatchedEvent)
err := rows.StructScan(lg)
err = rows.StructScan(lg)
if err != nil {
return nil, err
}
@@ -1,24 +1,27 @@
package postgres_test
package repositories_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
"github.com/vulcanize/vulcanizedb/pkg/filters"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("Watched Events Repository", func() {
var db *postgres.DB
var logRepository postgres.LogRepository
var filterRepository postgres.FilterRepository
var watchedEventRepository postgres.WatchedEventRepository
var logRepository datastore.LogRepository
var filterRepository datastore.FilterRepository
var watchedEventRepository datastore.WatchedEventRepository
BeforeEach(func() {
db = postgres.NewTestDB(core.Node{})
logRepository = postgres.LogRepository{DB: db}
filterRepository = postgres.FilterRepository{DB: db}
watchedEventRepository = postgres.WatchedEventRepository{DB: db}
db = test_config.NewTestDB(core.Node{})
logRepository = repositories.LogRepository{DB: db}
filterRepository = repositories.FilterRepository{DB: db}
watchedEventRepository = repositories.WatchedEventRepository{DB: db}
})
It("retrieves watched event logs that match the event filter", func() {
@@ -57,7 +60,15 @@ var _ = Describe("Watched Events Repository", func() {
Expect(err).ToNot(HaveOccurred())
matchingLogs, err := watchedEventRepository.GetWatchedEvents("Filter1")
Expect(err).ToNot(HaveOccurred())
Expect(matchingLogs).To(Equal(expectedWatchedEventLog))
Expect(len(matchingLogs)).To(Equal(1))
Expect(matchingLogs[0].Name).To(Equal(expectedWatchedEventLog[0].Name))
Expect(matchingLogs[0].BlockNumber).To(Equal(expectedWatchedEventLog[0].BlockNumber))
Expect(matchingLogs[0].TxHash).To(Equal(expectedWatchedEventLog[0].TxHash))
Expect(matchingLogs[0].Address).To(Equal(expectedWatchedEventLog[0].Address))
Expect(matchingLogs[0].Topic0).To(Equal(expectedWatchedEventLog[0].Topic0))
Expect(matchingLogs[0].Topic1).To(Equal(expectedWatchedEventLog[0].Topic1))
Expect(matchingLogs[0].Topic2).To(Equal(expectedWatchedEventLog[0].Topic2))
Expect(matchingLogs[0].Data).To(Equal(expectedWatchedEventLog[0].Data))
})
@@ -103,7 +114,14 @@ var _ = Describe("Watched Events Repository", func() {
Expect(err).ToNot(HaveOccurred())
matchingLogs, err := watchedEventRepository.GetWatchedEvents("Filter1")
Expect(err).ToNot(HaveOccurred())
Expect(matchingLogs).To(Equal(expectedWatchedEventLog))
Expect(len(matchingLogs)).To(Equal(1))
Expect(matchingLogs[0].Name).To(Equal(expectedWatchedEventLog[0].Name))
Expect(matchingLogs[0].BlockNumber).To(Equal(expectedWatchedEventLog[0].BlockNumber))
Expect(matchingLogs[0].TxHash).To(Equal(expectedWatchedEventLog[0].TxHash))
Expect(matchingLogs[0].Address).To(Equal(expectedWatchedEventLog[0].Address))
Expect(matchingLogs[0].Topic0).To(Equal(expectedWatchedEventLog[0].Topic0))
Expect(matchingLogs[0].Topic1).To(Equal(expectedWatchedEventLog[0].Topic1))
Expect(matchingLogs[0].Topic2).To(Equal(expectedWatchedEventLog[0].Topic2))
Expect(matchingLogs[0].Data).To(Equal(expectedWatchedEventLog[0].Data))
})
})
@@ -1,7 +1,6 @@
package repositories
package datastore
import (
"errors"
"fmt"
"github.com/vulcanize/vulcanizedb/pkg/core"
@@ -9,7 +8,7 @@ import (
)
var ErrBlockDoesNotExist = func(blockNumber int64) error {
return errors.New(fmt.Sprintf("Block number %d does not exist", blockNumber))
return fmt.Errorf("Block number %d does not exist", blockNumber)
}
type BlockRepository interface {
@@ -20,7 +19,7 @@ type BlockRepository interface {
}
var ErrContractDoesNotExist = func(contractHash string) error {
return errors.New(fmt.Sprintf("Contract %v does not exist", contractHash))
return fmt.Errorf("Contract %v does not exist", contractHash)
}
type ContractRepository interface {
@@ -30,7 +29,7 @@ type ContractRepository interface {
}
var ErrFilterDoesNotExist = func(name string) error {
return errors.New(fmt.Sprintf("filter %s does not exist", name))
return fmt.Errorf("filter %s does not exist", name)
}
type FilterRepository interface {
@@ -44,7 +43,7 @@ type LogRepository interface {
}
var ErrReceiptDoesNotExist = func(txHash string) error {
return errors.New(fmt.Sprintf("Receipt for tx: %v does not exist", txHash))
return fmt.Errorf("Receipt for tx: %v does not exist", txHash)
}
type ReceiptRepository interface {
+13 -8
View File
@@ -9,12 +9,17 @@ import (
)
type Blockchain struct {
logs map[string][]core.Log
blocks map[int64]core.Block
contractAttributes map[string]map[string]string
blocksChannel chan core.Block
WasToldToStop bool
node core.Node
logs map[string][]core.Log
blocks map[int64]core.Block
contractAttributes map[string]map[string]string
blocksChannel chan core.Block
WasToldToStop bool
node core.Node
ContractReturnValue []byte
}
func (blockchain *Blockchain) CallContract(contractHash string, input []byte, blockNumber *big.Int) ([]byte, error) {
return blockchain.ContractReturnValue, nil
}
func (blockchain *Blockchain) LastBlock() *big.Int {
@@ -50,7 +55,7 @@ func NewBlockchain() *Blockchain {
blocks: make(map[int64]core.Block),
logs: make(map[string][]core.Log),
contractAttributes: make(map[string]map[string]string),
node: core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "Geth"},
node: core.Node{GenesisBlock: "GENESIS", NetworkID: 1, ID: "x123", ClientName: "Geth"},
}
}
@@ -91,7 +96,7 @@ func (blockchain *Blockchain) GetAttributes(contract core.Contract) (core.Contra
var contractAttributes core.ContractAttributes
attributes, ok := blockchain.contractAttributes[contract.Hash+"-1"]
if ok {
for key, _ := range attributes {
for key := range attributes {
contractAttributes = append(contractAttributes, core.ContractAttribute{Name: key, Type: "string"})
}
}
+1 -1
View File
@@ -31,7 +31,7 @@ func (filterQuery *LogFilter) UnmarshalJSON(input []byte) error {
}{
Alias: (*Alias)(filterQuery),
}
if err := json.Unmarshal(input, &aux); err != nil {
if err = json.Unmarshal(input, &aux); err != nil {
return err
}
if filterQuery.Name == "" {
+7 -8
View File
@@ -25,20 +25,19 @@ type Response struct {
Result string
}
type EtherScanApi struct {
type EtherScanAPI struct {
client *http.Client
url string
}
func NewEtherScanClient(url string) *EtherScanApi {
return &EtherScanApi{
func NewEtherScanClient(url string) *EtherScanAPI {
return &EtherScanAPI{
client: &http.Client{Timeout: 10 * time.Second},
url: url,
}
}
func GenUrl(network string) string {
func GenURL(network string) string {
switch network {
case "ropsten":
return "https://ropsten.etherscan.io"
@@ -52,7 +51,7 @@ func GenUrl(network string) string {
}
//https://api.etherscan.io/api?module=contract&action=getabi&address=%s
func (e *EtherScanApi) GetAbi(contractHash string) (string, error) {
func (e *EtherScanAPI) GetAbi(contractHash string) (string, error) {
target := new(Response)
request := fmt.Sprintf("%s/api?module=contract&action=getabi&address=%s", e.url, contractHash)
r, err := e.client.Get(request)
@@ -60,8 +59,8 @@ func (e *EtherScanApi) GetAbi(contractHash string) (string, error) {
return "", ErrApiRequestFailed
}
defer r.Body.Close()
json.NewDecoder(r.Body).Decode(&target)
return target.Result, nil
err = json.NewDecoder(r.Body).Decode(&target)
return target.Result, err
}
func ParseAbiFile(abiFilePath string) (abi.ABI, error) {
+16 -19
View File
@@ -1,20 +1,16 @@
package geth_test
import (
"path/filepath"
"net/http"
"fmt"
"log"
"github.com/ethereum/go-ethereum/accounts/abi"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/ghttp"
cfg "github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/geth"
"github.com/vulcanize/vulcanizedb/test_config"
)
var _ = Describe("ABI files", func() {
@@ -22,7 +18,7 @@ var _ = Describe("ABI files", func() {
Describe("Reading ABI files", func() {
It("loads a valid ABI file", func() {
path := filepath.Join(cfg.ProjectRoot(), "pkg", "geth", "testing", "valid_abi.json")
path := test_config.ABIFilePath + "valid_abi.json"
contractAbi, err := geth.ParseAbiFile(path)
@@ -31,7 +27,7 @@ var _ = Describe("ABI files", func() {
})
It("reads the contents of a valid ABI file", func() {
path := filepath.Join(cfg.ProjectRoot(), "pkg", "geth", "testing", "valid_abi.json")
path := test_config.ABIFilePath + "valid_abi.json"
contractAbi, err := geth.ReadAbiFile(path)
@@ -40,7 +36,7 @@ var _ = Describe("ABI files", func() {
})
It("returns an error when the file does not exist", func() {
path := filepath.Join(cfg.ProjectRoot(), "pkg", "geth", "testing", "missing_abi.json")
path := test_config.ABIFilePath + "missing_abi.json"
contractAbi, err := geth.ParseAbiFile(path)
@@ -49,7 +45,7 @@ var _ = Describe("ABI files", func() {
})
It("returns an error when the file has invalid contents", func() {
path := filepath.Join(cfg.ProjectRoot(), "pkg", "geth", "testing", "invalid_abi.json")
path := test_config.ABIFilePath + "invalid_abi.json"
contractAbi, err := geth.ParseAbiFile(path)
@@ -61,19 +57,20 @@ var _ = Describe("ABI files", func() {
var (
server *ghttp.Server
client *geth.EtherScanApi
client *geth.EtherScanAPI
abiString string
err error
)
BeforeEach(func() {
server = ghttp.NewServer()
client = geth.NewEtherScanClient(server.URL())
path := filepath.Join(cfg.ProjectRoot(), "pkg", "geth", "testing", "sample_abi.json")
abiString, err := geth.ReadAbiFile(path)
path := test_config.ABIFilePath + "sample_abi.json"
abiString, err = geth.ReadAbiFile(path)
Expect(err).NotTo(HaveOccurred())
_, err = geth.ParseAbi(abiString)
if err != nil {
log.Fatalln("Could not parse ABI")
}
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
@@ -104,14 +101,14 @@ var _ = Describe("ABI files", func() {
Describe("Generating etherscan endpoints based on network", func() {
It("should return the main endpoint as the default", func() {
url := geth.GenUrl("")
url := geth.GenURL("")
Expect(url).To(Equal("https://api.etherscan.io"))
})
It("generates various test network endpoint if test network is supplied", func() {
ropstenUrl := geth.GenUrl("ropsten")
rinkebyUrl := geth.GenUrl("rinkeby")
kovanUrl := geth.GenUrl("kovan")
ropstenUrl := geth.GenURL("ropsten")
rinkebyUrl := geth.GenURL("rinkeby")
kovanUrl := geth.GenURL("kovan")
Expect(ropstenUrl).To(Equal("https://ropsten.etherscan.io"))
Expect(kovanUrl).To(Equal("https://kovan.etherscan.io"))
+5 -6
View File
@@ -12,12 +12,12 @@ import (
"golang.org/x/net/context"
)
type GethClient interface {
type Client interface {
TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error)
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
}
func ToCoreBlock(gethBlock *types.Block, client GethClient) core.Block {
func ToCoreBlock(gethBlock *types.Block, client Client) core.Block {
transactions := convertTransactionsToCore(gethBlock, client)
coreBlock := core.Block{
Difficulty: gethBlock.Difficulty().Int64(),
@@ -39,7 +39,7 @@ func ToCoreBlock(gethBlock *types.Block, client GethClient) core.Block {
return coreBlock
}
func convertTransactionsToCore(gethBlock *types.Block, client GethClient) []core.Transaction {
func convertTransactionsToCore(gethBlock *types.Block, client Client) []core.Transaction {
transactions := make([]core.Transaction, 0)
for i, gethTransaction := range gethBlock.Transactions() {
from, err := client.TransactionSender(context.Background(), gethTransaction, gethBlock.Hash(), uint(i))
@@ -56,7 +56,7 @@ func convertTransactionsToCore(gethBlock *types.Block, client GethClient) []core
return transactions
}
func appendReceiptToTransaction(client GethClient, transaction core.Transaction) (core.Transaction, error) {
func appendReceiptToTransaction(client Client, transaction core.Transaction) (core.Transaction, error) {
gethReceipt, err := client.TransactionReceipt(context.Background(), common.HexToHash(transaction.Hash))
if err != nil {
log.Println(err)
@@ -84,7 +84,6 @@ func transToCoreTrans(transaction *types.Transaction, from *common.Address) core
func addressToHex(to *common.Address) string {
if to == nil {
return ""
} else {
return to.Hex()
}
return to.Hex()
}
+2 -1
View File
@@ -29,12 +29,13 @@ func NewBlockchain(ipcPath string) *Blockchain {
blockchain := Blockchain{}
rpcClient, err := rpc.Dial(ipcPath)
if err != nil {
log.Println("Unable to connect to node")
log.Fatal(err)
}
client := ethclient.NewClient(rpcClient)
blockchain.node = node.Info(rpcClient)
if infura := isInfuraNode(ipcPath); infura {
blockchain.node.Id = "infura"
blockchain.node.ID = "infura"
blockchain.node.ClientName = "infura"
}
blockchain.client = client
+18 -2
View File
@@ -27,7 +27,7 @@ func (blockchain *Blockchain) GetAttribute(contract core.Contract, attributeName
if err != nil {
return nil, ErrInvalidStateAttribute
}
output, err := callContract(contract.Hash, input, blockchain, blockNumber)
output, err := blockchain.callContract(contract.Hash, input, blockNumber)
if err != nil {
return nil, err
}
@@ -38,7 +38,23 @@ func (blockchain *Blockchain) GetAttribute(contract core.Contract, attributeName
return result, nil
}
func callContract(contractHash string, input []byte, blockchain *Blockchain, blockNumber *big.Int) ([]byte, error) {
func (blockchain *Blockchain) FetchContractData(abiJSON string, address string, method string, methodArg interface{}, result interface{}, blockNumber int64) error {
parsed, err := ParseAbi(abiJSON)
if err != nil {
return err
}
input, err := parsed.Pack(method, methodArg)
if err != nil {
return err
}
output, err := blockchain.callContract(address, input, big.NewInt(blockNumber))
if err != nil {
return err
}
return parsed.Unpack(result, method, output)
}
func (blockchain *Blockchain) callContract(contractHash string, input []byte, blockNumber *big.Int) ([]byte, error) {
to := common.HexToAddress(contractHash)
msg := ethereum.CallMsg{To: &to, Data: input}
return blockchain.client.CallContract(context.Background(), msg, blockNumber)
+4 -4
View File
@@ -13,13 +13,13 @@ import (
func Info(client *rpc.Client) core.Node {
node := core.Node{}
node.NetworkId = NetworkId(client)
node.NetworkID = NetworkID(client)
node.GenesisBlock = GenesisBlock(client)
node.Id, node.ClientName = IdClientName(client)
node.ID, node.ClientName = IDClientName(client)
return node
}
func IdClientName(client *rpc.Client) (string, string) {
func IDClientName(client *rpc.Client) (string, string) {
var info p2p.NodeInfo
modules, _ := client.SupportedModules()
if _, ok := modules["admin"]; ok {
@@ -29,7 +29,7 @@ func IdClientName(client *rpc.Client) (string, string) {
return "", ""
}
func NetworkId(client *rpc.Client) float64 {
func NetworkID(client *rpc.Client) float64 {
var version string
client.CallContext(context.Background(), &version, "net_version")
networkId, _ := strconv.ParseFloat(version, 64)
+6 -4
View File
@@ -1,11 +1,11 @@
package testing
import (
"path/filepath"
"log"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/geth"
"github.com/vulcanize/vulcanizedb/test_config"
)
func FindAttribute(contractAttributes core.ContractAttributes, attributeName string) *core.ContractAttribute {
@@ -25,7 +25,9 @@ func SampleContract() core.Contract {
}
func sampleAbiFileContents() string {
abiFilepath := filepath.Join(config.ProjectRoot(), "pkg", "geth", "testing", "sample_abi.json")
abiFileContents, _ := geth.ReadAbiFile(abiFilepath)
abiFileContents, err := geth.ReadAbiFile(test_config.ABIFilePath + "sample_abi.json")
if err != nil {
log.Fatal(err)
}
return abiFileContents
}
-169
View File
@@ -1,169 +0,0 @@
package graphql_server
import (
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/filters"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
)
var Schema = `
schema {
query: Query
}
type Query {
logFilter(name: String!): LogFilter
watchedEvents(name: String!): WatchedEventList
}
type LogFilter {
name: String!
fromBlock: Int
toBlock: Int
address: String!
topics: [String]!
}
type WatchedEventList{
total: Int!
watchedEvents: [WatchedEvent]!
}
type WatchedEvent {
name: String!
blockNumber: Int!
address: String!
tx_hash: String!
topic0: String!
topic1: String!
topic2: String!
topic3: String!
data: String!
}
`
type GraphQLRepositories struct {
repositories.BlockRepository
repositories.LogRepository
repositories.WatchedEventRepository
repositories.FilterRepository
}
type Resolver struct {
graphQLRepositories GraphQLRepositories
}
func NewResolver(repositories GraphQLRepositories) *Resolver {
return &Resolver{graphQLRepositories: repositories}
}
func (r *Resolver) LogFilter(args struct {
Name string
}) (*logFilterResolver, error) {
logFilter, err := r.graphQLRepositories.GetFilter(args.Name)
if err != nil {
return &logFilterResolver{}, err
}
return &logFilterResolver{&logFilter}, nil
}
type logFilterResolver struct {
lf *filters.LogFilter
}
func (lfr *logFilterResolver) Name() string {
return lfr.lf.Name
}
func (lfr *logFilterResolver) FromBlock() *int32 {
fromBlock := int32(lfr.lf.FromBlock)
return &fromBlock
}
func (lfr *logFilterResolver) ToBlock() *int32 {
toBlock := int32(lfr.lf.ToBlock)
return &toBlock
}
func (lfr *logFilterResolver) Address() string {
return lfr.lf.Address
}
func (lfr *logFilterResolver) Topics() []*string {
var topics = make([]*string, 4)
for i := range topics {
if lfr.lf.Topics[i] != "" {
topics[i] = &lfr.lf.Topics[i]
}
}
return topics
}
func (r *Resolver) WatchedEvents(args struct {
Name string
}) (*watchedEventsResolver, error) {
watchedEvents, err := r.graphQLRepositories.GetWatchedEvents(args.Name)
if err != nil {
return &watchedEventsResolver{}, err
}
return &watchedEventsResolver{watchedEvents: watchedEvents}, err
}
type watchedEventsResolver struct {
watchedEvents []*core.WatchedEvent
}
func (wesr watchedEventsResolver) WatchedEvents() []*watchedEventResolver {
return resolveWatchedEvents(wesr.watchedEvents)
}
func (wesr watchedEventsResolver) Total() int32 {
return int32(len(wesr.watchedEvents))
}
func resolveWatchedEvents(watchedEvents []*core.WatchedEvent) []*watchedEventResolver {
watchedEventResolvers := make([]*watchedEventResolver, 0)
for _, watchedEvent := range watchedEvents {
watchedEventResolvers = append(watchedEventResolvers, &watchedEventResolver{watchedEvent})
}
return watchedEventResolvers
}
type watchedEventResolver struct {
we *core.WatchedEvent
}
func (wer watchedEventResolver) Name() string {
return wer.we.Name
}
func (wer watchedEventResolver) BlockNumber() int32 {
return int32(wer.we.BlockNumber)
}
func (wer watchedEventResolver) Address() string {
return wer.we.Address
}
func (wer watchedEventResolver) TxHash() string {
return wer.we.TxHash
}
func (wer watchedEventResolver) Topic0() string {
return wer.we.Topic0
}
func (wer watchedEventResolver) Topic1() string {
return wer.we.Topic1
}
func (wer watchedEventResolver) Topic2() string {
return wer.we.Topic2
}
func (wer watchedEventResolver) Topic3() string {
return wer.we.Topic3
}
func (wer watchedEventResolver) Data() string {
return wer.we.Data
}
-178
View File
@@ -1,178 +0,0 @@
package graphql_server_test
import (
"log"
"encoding/json"
"context"
"github.com/neelance/graphql-go"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/filters"
"github.com/vulcanize/vulcanizedb/pkg/graphql_server"
"github.com/vulcanize/vulcanizedb/pkg/repositories/postgres"
)
func formatJSON(data []byte) []byte {
var v interface{}
if err := json.Unmarshal(data, &v); err != nil {
log.Fatalf("invalid JSON: %s", err)
}
formatted, err := json.Marshal(v)
if err != nil {
log.Fatal(err)
}
return formatted
}
var _ = Describe("GraphQL", func() {
var cfg config.Config
var graphQLRepositories graphql_server.GraphQLRepositories
BeforeEach(func() {
cfg, _ = config.NewConfig("private")
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
db := postgres.NewTestDB(node)
blockRepository := &postgres.BlockRepository{DB: db}
logRepository := &postgres.LogRepository{DB: db}
filterRepository := &postgres.FilterRepository{DB: db}
watchedEventRepository := &postgres.WatchedEventRepository{DB: db}
graphQLRepositories = graphql_server.GraphQLRepositories{
WatchedEventRepository: watchedEventRepository,
BlockRepository: blockRepository,
LogRepository: logRepository,
FilterRepository: filterRepository,
}
err := graphQLRepositories.CreateFilter(filters.LogFilter{
Name: "TestFilter1",
FromBlock: 1,
ToBlock: 10,
Address: "0x123456789",
Topics: core.Topics{0: "topic=1", 2: "topic=2"},
})
if err != nil {
log.Fatal(err)
}
filter, err := graphQLRepositories.GetFilter("TestFilter1")
if err != nil {
log.Println(filter)
log.Fatal(err)
}
matchingEvent := core.Log{
BlockNumber: 5,
TxHash: "0xTX1",
Address: "0x123456789",
Topics: core.Topics{0: "topic=1", 2: "topic=2"},
Index: 0,
Data: "0xDATADATADATA",
}
nonMatchingEvent := core.Log{
BlockNumber: 5,
TxHash: "0xTX2",
Address: "0xOTHERADDRESS",
Topics: core.Topics{0: "topic=1", 2: "topic=2"},
Index: 0,
Data: "0xDATADATADATA",
}
err = graphQLRepositories.CreateLogs([]core.Log{matchingEvent, nonMatchingEvent})
if err != nil {
log.Fatal(err)
}
})
It("Queries example schema for specific log filter", func() {
var variables map[string]interface{}
resolver := graphql_server.NewResolver(graphQLRepositories)
var schema = graphql.MustParseSchema(graphql_server.Schema, resolver)
response := schema.Exec(context.Background(),
`{
logFilter(name: "TestFilter1") {
name
fromBlock
toBlock
address
topics
}
}`,
"",
variables)
expected := `{
"logFilter": {
"name": "TestFilter1",
"fromBlock": 1,
"toBlock": 10,
"address": "0x123456789",
"topics": ["topic=1", null, "topic=2", null]
}
}`
var v interface{}
if len(response.Errors) != 0 {
log.Fatal(response.Errors)
}
err := json.Unmarshal(response.Data, &v)
Expect(err).ToNot(HaveOccurred())
actualJSON := formatJSON(response.Data)
expectedJSON := formatJSON([]byte(expected))
Expect(actualJSON).To(Equal(expectedJSON))
})
It("Queries example schema for specific watched event log", func() {
var variables map[string]interface{}
resolver := graphql_server.NewResolver(graphQLRepositories)
var schema = graphql.MustParseSchema(graphql_server.Schema, resolver)
response := schema.Exec(context.Background(),
`{
watchedEvents(name: "TestFilter1") {
total
watchedEvents{
name
blockNumber
address
tx_hash
topic0
topic1
topic2
topic3
data
}
}
}`,
"",
variables)
expected := `{
"watchedEvents":
{
"total": 1,
"watchedEvents": [
{"name":"TestFilter1",
"blockNumber": 5,
"address": "0x123456789",
"tx_hash": "0xTX1",
"topic0": "topic=1",
"topic1": "",
"topic2": "topic=2",
"topic3": "",
"data": "0xDATADATADATA"
}
]
}
}`
var v interface{}
if len(response.Errors) != 0 {
log.Fatal(response.Errors)
}
err := json.Unmarshal(response.Data, &v)
Expect(err).ToNot(HaveOccurred())
actualJSON := formatJSON(response.Data)
expectedJSON := formatJSON([]byte(expected))
Expect(actualJSON).To(Equal(expectedJSON))
})
})
+3 -3
View File
@@ -4,10 +4,10 @@ import (
"log"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
)
func PopulateMissingBlocks(blockchain core.Blockchain, blockRepository repositories.BlockRepository, startingBlockNumber int64) int {
func PopulateMissingBlocks(blockchain core.Blockchain, blockRepository datastore.BlockRepository, startingBlockNumber int64) int {
lastBlock := blockchain.LastBlock().Int64()
blockRange := blockRepository.MissingBlockNumbers(startingBlockNumber, lastBlock-1)
log.SetPrefix("")
@@ -16,7 +16,7 @@ func PopulateMissingBlocks(blockchain core.Blockchain, blockRepository repositor
return len(blockRange)
}
func RetrieveAndUpdateBlocks(blockchain core.Blockchain, blockRepository repositories.BlockRepository, blockNumbers []int64) int {
func RetrieveAndUpdateBlocks(blockchain core.Blockchain, blockRepository datastore.BlockRepository, blockNumbers []int64) int {
for _, blockNumber := range blockNumbers {
block := blockchain.GetBlockByNumber(blockNumber)
blockRepository.CreateOrUpdateBlock(block)
+1 -1
View File
@@ -4,9 +4,9 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/inmemory"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/history"
"github.com/vulcanize/vulcanizedb/pkg/repositories/inmemory"
)
var _ = Describe("Populating blocks", func() {
+3 -3
View File
@@ -5,7 +5,7 @@ import (
"text/template"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/repositories"
"github.com/vulcanize/vulcanizedb/pkg/datastore"
)
const WindowTemplate = `Validating Blocks
@@ -17,12 +17,12 @@ var ParsedWindowTemplate = *template.Must(template.New("window").Parse(WindowTem
type BlockValidator struct {
blockchain core.Blockchain
blockRepository repositories.BlockRepository
blockRepository datastore.BlockRepository
windowSize int
parsedLoggingTemplate template.Template
}
func NewBlockValidator(blockchain core.Blockchain, blockRepository repositories.BlockRepository, windowSize int) *BlockValidator {
func NewBlockValidator(blockchain core.Blockchain, blockRepository datastore.BlockRepository, windowSize int) *BlockValidator {
return &BlockValidator{
blockchain,
blockRepository,
+1 -1
View File
@@ -9,9 +9,9 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vulcanize/vulcanizedb/pkg/core"
"github.com/vulcanize/vulcanizedb/pkg/datastore/inmemory"
"github.com/vulcanize/vulcanizedb/pkg/fakes"
"github.com/vulcanize/vulcanizedb/pkg/history"
"github.com/vulcanize/vulcanizedb/pkg/repositories/inmemory"
)
func init() {
-22
View File
@@ -1,22 +0,0 @@
package postgres
import (
"github.com/vulcanize/vulcanizedb/pkg/config"
"github.com/vulcanize/vulcanizedb/pkg/core"
)
func (db *DB) clearData() {
db.MustExec("DELETE FROM watched_contracts")
db.MustExec("DELETE FROM transactions")
db.MustExec("DELETE FROM blocks")
db.MustExec("DELETE FROM logs")
db.MustExec("DELETE FROM receipts")
db.MustExec("DELETE FROM log_filters")
}
func NewTestDB(node core.Node) *DB {
cfg, _ := config.NewConfig("private")
db, _ := NewDB(cfg.Database, node)
db.clearData()
return db
}