forked from cerc-io/ipld-eth-server
adjusted FetchContractData to work with variable number of contract method arguments, changed fetcher's FetchSupply method to more general FetchBigInt method and added FetchBool and FetchAddress methods
This commit is contained in:
parent
93960e7c4e
commit
ccd21f73c9
@ -19,45 +19,54 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Interface definition for a Fetcher
|
||||||
type ERC20FetcherInterface interface {
|
type ERC20FetcherInterface interface {
|
||||||
FetchSupplyOf(contractAbi string, contractAddress string, blockNumber int64) (big.Int, error)
|
FetchBigInt(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error)
|
||||||
|
FetchBool(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (bool, error)
|
||||||
|
FetchAddress(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (common.Address, error)
|
||||||
GetBlockChain() core.BlockChain
|
GetBlockChain() core.BlockChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFetcher(blockchain core.BlockChain) Fetcher {
|
// Initializes and returns a Fetcher with the given blockchain
|
||||||
|
func NewFetcher(blockChain core.BlockChain) Fetcher {
|
||||||
return Fetcher{
|
return Fetcher{
|
||||||
Blockchain: blockchain,
|
BlockChain: blockChain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetcher struct
|
||||||
type Fetcher struct {
|
type Fetcher struct {
|
||||||
Blockchain core.BlockChain
|
BlockChain core.BlockChain
|
||||||
ContractAbi string
|
ContractAbi string
|
||||||
ContractAddress string
|
ContractAddress string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetcher error
|
||||||
type fetcherError struct {
|
type fetcherError struct {
|
||||||
err string
|
err string
|
||||||
fetchMethod string
|
fetchMethod string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetcher error method
|
||||||
func (fe *fetcherError) Error() string {
|
func (fe *fetcherError) Error() string {
|
||||||
return fmt.Sprintf("Error fetching %s: %s", fe.fetchMethod, fe.err)
|
return fmt.Sprintf("Error fetching %s: %s", fe.fetchMethod, fe.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to create a new Fetcher error for a given error and fetch method
|
||||||
func newFetcherError(err error, fetchMethod string) *fetcherError {
|
func newFetcherError(err error, fetchMethod string) *fetcherError {
|
||||||
e := fetcherError{err.Error(), fetchMethod}
|
e := fetcherError{err.Error(), fetchMethod}
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
return &e
|
return &e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Fetcher) FetchSupplyOf(contractAbi string, contractAddress string, blockNumber int64) (big.Int, error) {
|
// Method used to fetch big.Int result from contract
|
||||||
method := "totalSupply"
|
func (f Fetcher) FetchBigInt(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) {
|
||||||
var result = new(big.Int)
|
var result = new(big.Int)
|
||||||
err := f.Blockchain.FetchContractData(contractAbi, contractAddress, method, nil, &result, blockNumber)
|
err := f.BlockChain.FetchContractData(contractAbi, contractAddress, method, methodArgs, &result, blockNumber)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return *result, newFetcherError(err, method)
|
return *result, newFetcherError(err, method)
|
||||||
@ -66,6 +75,31 @@ func (f Fetcher) FetchSupplyOf(contractAbi string, contractAddress string, block
|
|||||||
return *result, nil
|
return *result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f Fetcher) GetBlockChain() core.BlockChain {
|
// Method used to fetch bool result from contract
|
||||||
return f.Blockchain
|
func (f Fetcher) FetchBool(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (bool, error) {
|
||||||
|
var result = new(bool)
|
||||||
|
err := f.BlockChain.FetchContractData(contractAbi, contractAddress, method, methodArgs, &result, blockNumber)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *result, newFetcherError(err, method)
|
||||||
|
}
|
||||||
|
|
||||||
|
return *result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method used to fetch address result from contract
|
||||||
|
func (f Fetcher) FetchAddress(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (common.Address, error) {
|
||||||
|
var result = new(common.Address)
|
||||||
|
err := f.BlockChain.FetchContractData(contractAbi, contractAddress, method, methodArgs, &result, blockNumber)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return *result, newFetcherError(err, method)
|
||||||
|
}
|
||||||
|
|
||||||
|
return *result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter method for Fetcher's blockchain
|
||||||
|
func (f Fetcher) GetBlockChain() core.BlockChain {
|
||||||
|
return f.BlockChain
|
||||||
}
|
}
|
||||||
|
@ -34,22 +34,23 @@ import (
|
|||||||
var _ = Describe("ERC20 Fetcher", func() {
|
var _ = Describe("ERC20 Fetcher", func() {
|
||||||
blockNumber := int64(5502914)
|
blockNumber := int64(5502914)
|
||||||
|
|
||||||
Describe("FetchSupplyOf", func() {
|
Describe("totalSupply", func() {
|
||||||
It("fetches data from the blockchain with the correct arguments", func() {
|
It("fetches total supply data from the blockchain with the correct arguments", func() {
|
||||||
fakeBlockchain := fakes.NewMockBlockChain()
|
fakeBlockChain := fakes.NewMockBlockChain()
|
||||||
testFetcher := every_block.NewFetcher(fakeBlockchain)
|
testFetcher := every_block.NewFetcher(fakeBlockChain)
|
||||||
testAbi := "testAbi"
|
testAbi := "testAbi"
|
||||||
testContractAddress := "testContractAddress"
|
testContractAddress := "testContractAddress"
|
||||||
_, err := testFetcher.FetchSupplyOf(testAbi, testContractAddress, blockNumber)
|
|
||||||
|
_, err := testFetcher.FetchBigInt("totalSupply", testAbi, testContractAddress, blockNumber, nil)
|
||||||
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
expectedResult := big.Int{}
|
expectedResult := big.Int{}
|
||||||
expected := &expectedResult
|
expected := &expectedResult
|
||||||
fakeBlockchain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "totalSupply", nil, &expected, blockNumber)
|
fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "totalSupply", nil, &expected, blockNumber)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("fetches a token's total supply at the given block height", func() {
|
It("fetches dai token's total supply at the given block height", func() {
|
||||||
infuraIPC := "https://mainnet.infura.io/J5Vd2fRtGsw0zZ0Ov3BL"
|
infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05"
|
||||||
rawRpcClient, err := rpc.Dial(infuraIPC)
|
rawRpcClient, err := rpc.Dial(infuraIPC)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC)
|
rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC)
|
||||||
@ -59,7 +60,7 @@ var _ = Describe("ERC20 Fetcher", func() {
|
|||||||
transactionConverter := rpc2.NewRpcTransactionConverter(ethClient)
|
transactionConverter := rpc2.NewRpcTransactionConverter(ethClient)
|
||||||
blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter)
|
blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter)
|
||||||
realFetcher := every_block.NewFetcher(blockChain)
|
realFetcher := every_block.NewFetcher(blockChain)
|
||||||
result, err := realFetcher.FetchSupplyOf(constants.DaiAbiString, constants.DaiContractAddress, blockNumber)
|
result, err := realFetcher.FetchBigInt("totalSupply", constants.DaiAbiString, constants.DaiContractAddress, blockNumber, nil)
|
||||||
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
expectedResult := big.Int{}
|
expectedResult := big.Int{}
|
||||||
@ -71,7 +72,7 @@ var _ = Describe("ERC20 Fetcher", func() {
|
|||||||
blockChain := fakes.NewMockBlockChain()
|
blockChain := fakes.NewMockBlockChain()
|
||||||
blockChain.SetFetchContractDataErr(fakes.FakeError)
|
blockChain.SetFetchContractDataErr(fakes.FakeError)
|
||||||
errorFetcher := every_block.NewFetcher(blockChain)
|
errorFetcher := every_block.NewFetcher(blockChain)
|
||||||
result, err := errorFetcher.FetchSupplyOf("", "", 0)
|
result, err := errorFetcher.FetchBigInt("totalSupply", "", "", 0, nil)
|
||||||
|
|
||||||
Expect(result.String()).To(Equal("0"))
|
Expect(result.String()).To(Equal("0"))
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
@ -79,4 +80,4 @@ var _ = Describe("ERC20 Fetcher", func() {
|
|||||||
Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error()))
|
Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
@ -14,8 +14,26 @@
|
|||||||
|
|
||||||
package every_block
|
package every_block
|
||||||
|
|
||||||
|
// Struct to hold token supply data
|
||||||
type TokenSupply struct {
|
type TokenSupply struct {
|
||||||
Value string
|
Value string
|
||||||
TokenAddress string
|
TokenAddress string
|
||||||
BlockNumber int64
|
BlockNumber int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Struct to hold token holder address balance data
|
||||||
|
type TokenBalance struct {
|
||||||
|
Value string
|
||||||
|
TokenAddress string
|
||||||
|
BlockNumber int64
|
||||||
|
TokenHolderAddress string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Struct to hold token allowance data
|
||||||
|
type TokenAllowance struct {
|
||||||
|
Value string
|
||||||
|
TokenAddress string
|
||||||
|
BlockNumber int64
|
||||||
|
TokenHolderAddress string
|
||||||
|
TokenSpenderAddress string
|
||||||
|
}
|
||||||
|
@ -20,38 +20,46 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Interface definition for a generic ERC20 token repository
|
||||||
type ERC20RepositoryInterface interface {
|
type ERC20RepositoryInterface interface {
|
||||||
Create(supply TokenSupply) error
|
CreateSupply(supply TokenSupply) error
|
||||||
MissingBlocks(startingBlock int64, highestBlock int64) ([]int64, error)
|
MissingSupplyBlocks(startingBlock, highestBlock int64, tokenAddress string) ([]int64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TokenSupplyRepository struct {
|
// Generic ERC20 token Repo struct
|
||||||
|
type ERC20TokenRepository struct {
|
||||||
*postgres.DB
|
*postgres.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Repo error
|
||||||
type repositoryError struct {
|
type repositoryError struct {
|
||||||
err string
|
err string
|
||||||
msg string
|
msg string
|
||||||
blockNumber int64
|
blockNumber int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Repo error method
|
||||||
func (re *repositoryError) Error() string {
|
func (re *repositoryError) Error() string {
|
||||||
return fmt.Sprintf(re.msg, re.blockNumber, re.err)
|
return fmt.Sprintf(re.msg, re.blockNumber, re.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to create a new Repo error for a given error and fetch method
|
||||||
func newRepositoryError(err error, msg string, blockNumber int64) error {
|
func newRepositoryError(err error, msg string, blockNumber int64) error {
|
||||||
e := repositoryError{err.Error(), msg, blockNumber}
|
e := repositoryError{err.Error(), msg, blockNumber}
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
return &e
|
return &e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constant error definitions
|
||||||
const (
|
const (
|
||||||
GetBlockError = "Error fetching block number %d: %s"
|
GetBlockError = "Error fetching block number %d: %s"
|
||||||
InsertTokenSupplyError = "Error inserting token_supply for block number %d: %s"
|
InsertTokenSupplyError = "Error inserting token_supply for block number %d: %s"
|
||||||
MissingBlockError = "Error finding missing token_supply records starting at block %d: %s"
|
MissingBlockError = "Error finding missing token_supply records starting at block %d: %s"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (tsp *TokenSupplyRepository) Create(supply TokenSupply) error {
|
// Supply methods
|
||||||
|
// This method inserts the supply for a given token contract address at a given block height into the token_supply table
|
||||||
|
func (tsp *ERC20TokenRepository) CreateSupply(supply TokenSupply) error {
|
||||||
var blockId int
|
var blockId int
|
||||||
err := tsp.DB.Get(&blockId, `SELECT id FROM blocks WHERE number = $1 AND eth_node_id = $2`, supply.BlockNumber, tsp.NodeID)
|
err := tsp.DB.Get(&blockId, `SELECT id FROM blocks WHERE number = $1 AND eth_node_id = $2`, supply.BlockNumber, tsp.NodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -68,7 +76,8 @@ func (tsp *TokenSupplyRepository) Create(supply TokenSupply) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tsp *TokenSupplyRepository) MissingBlocks(startingBlock int64, highestBlock int64) ([]int64, error) {
|
// This method returns an array of blocks that are missing a token_supply entry for a given tokenAddress
|
||||||
|
func (tsp *ERC20TokenRepository) MissingSupplyBlocks(startingBlock, highestBlock int64, tokenAddress string) ([]int64, error) {
|
||||||
blockNumbers := make([]int64, 0)
|
blockNumbers := make([]int64, 0)
|
||||||
|
|
||||||
err := tsp.DB.Select(
|
err := tsp.DB.Select(
|
||||||
@ -88,4 +97,4 @@ func (tsp *TokenSupplyRepository) MissingBlocks(startingBlock int64, highestBloc
|
|||||||
return []int64{}, newRepositoryError(err, MissingBlockError, startingBlock)
|
return []int64{}, newRepositoryError(err, MissingBlockError, startingBlock)
|
||||||
}
|
}
|
||||||
return blockNumbers, err
|
return blockNumbers, err
|
||||||
}
|
}
|
@ -31,13 +31,13 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
var db *postgres.DB
|
var db *postgres.DB
|
||||||
var blockId int64
|
var blockId int64
|
||||||
var blockNumber int64
|
var blockNumber int64
|
||||||
var repository every_block.TokenSupplyRepository
|
var repository every_block.ERC20TokenRepository
|
||||||
var blockRepository repositories.BlockRepository
|
var blockRepository repositories.BlockRepository
|
||||||
testAddress := "abc"
|
testAddress := "abc"
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
db = test_helpers.CreateNewDatabase()
|
db = test_helpers.CreateNewDatabase()
|
||||||
repository = every_block.TokenSupplyRepository{DB: db}
|
repository = every_block.ERC20TokenRepository{DB: db}
|
||||||
_, err := db.Query(`DELETE FROM token_supply`)
|
_, err := db.Query(`DELETE FROM token_supply`)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
Describe("Create", func() {
|
Describe("Create", func() {
|
||||||
It("creates a token supply record", func() {
|
It("creates a token supply record", func() {
|
||||||
supply := supplyModel(blockNumber, testAddress, "100")
|
supply := supplyModel(blockNumber, testAddress, "100")
|
||||||
err := repository.Create(supply)
|
err := repository.CreateSupply(supply)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
dbResult := test_helpers.TokenSupplyDBRow{}
|
dbResult := test_helpers.TokenSupplyDBRow{}
|
||||||
@ -73,7 +73,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
|
|
||||||
It("returns an error if fetching the block's id from the database fails", func() {
|
It("returns an error if fetching the block's id from the database fails", func() {
|
||||||
errorSupply := supplyModel(-1, "", "")
|
errorSupply := supplyModel(-1, "", "")
|
||||||
err := repository.Create(errorSupply)
|
err := repository.CreateSupply(errorSupply)
|
||||||
|
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("sql"))
|
Expect(err.Error()).To(ContainSubstring("sql"))
|
||||||
@ -82,7 +82,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
|
|
||||||
It("returns an error if inserting the token_supply fails", func() {
|
It("returns an error if inserting the token_supply fails", func() {
|
||||||
errorSupply := supplyModel(blockNumber, "", "")
|
errorSupply := supplyModel(blockNumber, "", "")
|
||||||
err := repository.Create(errorSupply)
|
err := repository.CreateSupply(errorSupply)
|
||||||
|
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(err.Error()).To(ContainSubstring("pq"))
|
Expect(err.Error()).To(ContainSubstring("pq"))
|
||||||
@ -94,7 +94,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
var node2DB *postgres.DB
|
var node2DB *postgres.DB
|
||||||
var node2BlockRepo *repositories.BlockRepository
|
var node2BlockRepo *repositories.BlockRepository
|
||||||
var node2BlockId int64
|
var node2BlockId int64
|
||||||
var node2TokenSupplyRepo every_block.TokenSupplyRepository
|
var node2TokenSupplyRepo every_block.ERC20TokenRepository
|
||||||
var tokenSupply every_block.TokenSupply
|
var tokenSupply every_block.TokenSupply
|
||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
@ -105,11 +105,11 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
node2BlockId = test_helpers.CreateBlock(blockNumber, *node2BlockRepo)
|
node2BlockId = test_helpers.CreateBlock(blockNumber, *node2BlockRepo)
|
||||||
|
|
||||||
tokenSupply = supplyModel(blockNumber, "abc", "100")
|
tokenSupply = supplyModel(blockNumber, "abc", "100")
|
||||||
node2TokenSupplyRepo = every_block.TokenSupplyRepository{DB: node2DB}
|
node2TokenSupplyRepo = every_block.ERC20TokenRepository{DB: node2DB}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("only creates token_supply records for the current node (node2)", func() {
|
It("only creates token_supply records for the current node (node2)", func() {
|
||||||
err := node2TokenSupplyRepo.Create(tokenSupply)
|
err := node2TokenSupplyRepo.CreateSupply(tokenSupply)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
var tokenSupplies []test_helpers.TokenSupplyDBRow
|
var tokenSupplies []test_helpers.TokenSupplyDBRow
|
||||||
@ -121,14 +121,14 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
|
|
||||||
It("only includes missing block numbers for the current node", func() {
|
It("only includes missing block numbers for the current node", func() {
|
||||||
//create token_supply on original node
|
//create token_supply on original node
|
||||||
err := repository.Create(tokenSupply)
|
err := repository.CreateSupply(tokenSupply)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
originalNodeMissingBlocks, err := repository.MissingBlocks(blockNumber, blockNumber)
|
originalNodeMissingBlocks, err := repository.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(len(originalNodeMissingBlocks)).To(Equal(0))
|
Expect(len(originalNodeMissingBlocks)).To(Equal(0))
|
||||||
|
|
||||||
node2MissingBlocks, err := node2TokenSupplyRepo.MissingBlocks(blockNumber, blockNumber)
|
node2MissingBlocks, err := node2TokenSupplyRepo.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(len(node2MissingBlocks)).To(Equal(1))
|
Expect(len(node2MissingBlocks)).To(Equal(1))
|
||||||
})
|
})
|
||||||
@ -140,7 +140,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
|
|
||||||
newBlockNumber := blockNumber + 1
|
newBlockNumber := blockNumber + 1
|
||||||
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
||||||
blocks, err := repository.MissingBlocks(blockNumber, newBlockNumber)
|
blocks, err := repository.MissingSupplyBlocks(blockNumber, newBlockNumber, testAddress)
|
||||||
|
|
||||||
Expect(blocks).To(ConsistOf(newBlockNumber))
|
Expect(blocks).To(ConsistOf(newBlockNumber))
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -149,7 +149,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
It("only returns blocks within the given range", func() {
|
It("only returns blocks within the given range", func() {
|
||||||
newBlockNumber := blockNumber + 1
|
newBlockNumber := blockNumber + 1
|
||||||
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
||||||
blocks, err := repository.MissingBlocks(blockNumber, blockNumber)
|
blocks, err := repository.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
||||||
|
|
||||||
Expect(blocks).NotTo(ConsistOf(newBlockNumber))
|
Expect(blocks).NotTo(ConsistOf(newBlockNumber))
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -157,7 +157,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
|
|
||||||
It("does not return numbers that already have an associated TokenSupply record", func() {
|
It("does not return numbers that already have an associated TokenSupply record", func() {
|
||||||
createTokenSupplyFor(repository, blockNumber)
|
createTokenSupplyFor(repository, blockNumber)
|
||||||
blocks, err := repository.MissingBlocks(blockNumber, blockNumber)
|
blocks, err := repository.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
||||||
|
|
||||||
Expect(blocks).To(BeEmpty())
|
Expect(blocks).To(BeEmpty())
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -165,7 +165,7 @@ var _ = Describe("ERC20 Token Repository", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("deletes the token supply record when the associated block is deleted", func() {
|
It("deletes the token supply record when the associated block is deleted", func() {
|
||||||
err := repository.Create(every_block.TokenSupply{BlockNumber: blockNumber, Value: "0"})
|
err := repository.CreateSupply(every_block.TokenSupply{BlockNumber: blockNumber, Value: "0"})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
var count int
|
var count int
|
||||||
@ -190,8 +190,8 @@ func supplyModel(blockNumber int64, tokenAddress string, supplyValue string) eve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTokenSupplyFor(repository every_block.TokenSupplyRepository, blockNumber int64) {
|
func createTokenSupplyFor(repository every_block.ERC20TokenRepository, blockNumber int64) {
|
||||||
err := repository.Create(every_block.TokenSupply{BlockNumber: blockNumber, Value: "0"})
|
err := repository.CreateSupply(every_block.TokenSupply{BlockNumber: blockNumber, Value: "0"})
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ type TokenSupplyTransformerInitializer struct {
|
|||||||
|
|
||||||
func (i TokenSupplyTransformerInitializer) NewTokenSupplyTransformer(db *postgres.DB, blockchain core.BlockChain) shared.Transformer {
|
func (i TokenSupplyTransformerInitializer) NewTokenSupplyTransformer(db *postgres.DB, blockchain core.BlockChain) shared.Transformer {
|
||||||
fetcher := NewFetcher(blockchain)
|
fetcher := NewFetcher(blockchain)
|
||||||
repository := TokenSupplyRepository{DB: db}
|
repository := ERC20TokenRepository{DB: db}
|
||||||
transformer := Transformer{
|
transformer := Transformer{
|
||||||
Fetcher: &fetcher,
|
Fetcher: &fetcher,
|
||||||
Repository: &repository,
|
Repository: &repository,
|
||||||
@ -83,21 +83,29 @@ func (t Transformer) Execute() error {
|
|||||||
upperBoundBlock = t.Config.LastBlock
|
upperBoundBlock = t.Config.LastBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks, err := t.Repository.MissingBlocks(t.Config.FirstBlock, upperBoundBlock)
|
// Supply transformations:
|
||||||
|
|
||||||
|
// Fetch missing supply blocks
|
||||||
|
blocks, err := t.Repository.MissingSupplyBlocks(t.Config.FirstBlock, upperBoundBlock, t.Config.Address)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newTransformerError(err, t.Config.FirstBlock, FetchingBlocksError)
|
return newTransformerError(err, t.Config.FirstBlock, FetchingBlocksError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch supply for missing blocks
|
||||||
log.Printf("Fetching totalSupply for %d blocks", len(blocks))
|
log.Printf("Fetching totalSupply for %d blocks", len(blocks))
|
||||||
|
|
||||||
|
// For each block missing total supply, create supply model and feed the missing data into the repository
|
||||||
for _, blockNumber := range blocks {
|
for _, blockNumber := range blocks {
|
||||||
totalSupply, err := t.Fetcher.FetchSupplyOf(t.Config.Abi, t.Config.Address, blockNumber)
|
totalSupply, err := t.Fetcher.FetchBigInt("totalSupply", t.Config.Abi, t.Config.Address, blockNumber, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newTransformerError(err, blockNumber, FetchingSupplyError)
|
return newTransformerError(err, blockNumber, FetchingSupplyError)
|
||||||
}
|
}
|
||||||
|
// Create the supply model
|
||||||
model := createTokenSupplyModel(totalSupply, t.Config.Address, blockNumber)
|
model := createTokenSupplyModel(totalSupply, t.Config.Address, blockNumber)
|
||||||
err = t.Repository.Create(model)
|
// Feed it into the repository
|
||||||
|
err = t.Repository.CreateSupply(model)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newTransformerError(err, blockNumber, CreateSupplyError)
|
return newTransformerError(err, blockNumber, CreateSupplyError)
|
||||||
|
@ -39,7 +39,7 @@ var config = testContractConfig
|
|||||||
|
|
||||||
var _ = Describe("Everyblock transformer", func() {
|
var _ = Describe("Everyblock transformer", func() {
|
||||||
var fetcher mocks.Fetcher
|
var fetcher mocks.Fetcher
|
||||||
var repository mocks.TotalSupplyRepository
|
var repository mocks.ERC20TokenRepository
|
||||||
var transformer every_block.Transformer
|
var transformer every_block.Transformer
|
||||||
var blockChain *fakes.MockBlockChain
|
var blockChain *fakes.MockBlockChain
|
||||||
var initialSupply = "27647235749155415536952630"
|
var initialSupply = "27647235749155415536952630"
|
||||||
@ -53,8 +53,8 @@ var _ = Describe("Everyblock transformer", func() {
|
|||||||
blockChain.SetLastBlock(&defaultLastBlock)
|
blockChain.SetLastBlock(&defaultLastBlock)
|
||||||
fetcher = mocks.Fetcher{BlockChain: blockChain}
|
fetcher = mocks.Fetcher{BlockChain: blockChain}
|
||||||
fetcher.SetSupply(initialSupply)
|
fetcher.SetSupply(initialSupply)
|
||||||
repository = mocks.TotalSupplyRepository{}
|
repository = mocks.ERC20TokenRepository{}
|
||||||
repository.SetMissingBlocks([]int64{config.FirstBlock})
|
repository.SetMissingSupplyBlocks([]int64{config.FirstBlock})
|
||||||
//setting the mock repository to return the first block as the missing blocks
|
//setting the mock repository to return the first block as the missing blocks
|
||||||
|
|
||||||
transformer = every_block.Transformer{
|
transformer = every_block.Transformer{
|
||||||
@ -89,8 +89,9 @@ var _ = Describe("Everyblock transformer", func() {
|
|||||||
config.FirstBlock + 1,
|
config.FirstBlock + 1,
|
||||||
config.FirstBlock + 2,
|
config.FirstBlock + 2,
|
||||||
}
|
}
|
||||||
repository.SetMissingBlocks(missingBlocks)
|
repository.SetMissingSupplyBlocks(missingBlocks)
|
||||||
transformer.Execute()
|
err := transformer.Execute()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
Expect(len(fetcher.FetchedBlocks)).To(Equal(3))
|
Expect(len(fetcher.FetchedBlocks)).To(Equal(3))
|
||||||
Expect(fetcher.FetchedBlocks).To(ConsistOf(config.FirstBlock, config.FirstBlock+1, config.FirstBlock+2))
|
Expect(fetcher.FetchedBlocks).To(ConsistOf(config.FirstBlock, config.FirstBlock+1, config.FirstBlock+2))
|
||||||
@ -104,7 +105,7 @@ var _ = Describe("Everyblock transformer", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("uses the set contract configuration", func() {
|
It("uses the set contract configuration", func() {
|
||||||
repository.SetMissingBlocks([]int64{testContractConfig.FirstBlock})
|
repository.SetMissingSupplyBlocks([]int64{testContractConfig.FirstBlock})
|
||||||
transformer.SetConfiguration(testContractConfig)
|
transformer.SetConfiguration(testContractConfig)
|
||||||
err := transformer.Execute()
|
err := transformer.Execute()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
@ -143,7 +144,7 @@ var _ = Describe("Everyblock transformer", func() {
|
|||||||
|
|
||||||
It("returns an error if the call to get missing blocks fails", func() {
|
It("returns an error if the call to get missing blocks fails", func() {
|
||||||
failureRepository := mocks.FailureRepository{}
|
failureRepository := mocks.FailureRepository{}
|
||||||
failureRepository.SetMissingBlocksFail(true)
|
failureRepository.SetMissingSupplyBlocksFail(true)
|
||||||
transformer = every_block.Transformer{
|
transformer = every_block.Transformer{
|
||||||
Fetcher: &fetcher,
|
Fetcher: &fetcher,
|
||||||
Repository: &failureRepository,
|
Repository: &failureRepository,
|
||||||
@ -171,8 +172,8 @@ var _ = Describe("Everyblock transformer", func() {
|
|||||||
|
|
||||||
It("returns an error if the call to save the token_supply fails", func() {
|
It("returns an error if the call to save the token_supply fails", func() {
|
||||||
failureRepository := mocks.FailureRepository{}
|
failureRepository := mocks.FailureRepository{}
|
||||||
failureRepository.SetMissingBlocks([]int64{config.FirstBlock})
|
failureRepository.SetMissingSupplyBlocks([]int64{config.FirstBlock})
|
||||||
failureRepository.SetCreateFail(true)
|
failureRepository.SetCreateSupplyFail(true)
|
||||||
|
|
||||||
transformer = every_block.Transformer{
|
transformer = every_block.Transformer{
|
||||||
Fetcher: &fetcher,
|
Fetcher: &fetcher,
|
||||||
|
@ -15,11 +15,14 @@
|
|||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block"
|
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block"
|
||||||
"github.com/vulcanize/vulcanizedb/pkg/core"
|
"github.com/vulcanize/vulcanizedb/pkg/core"
|
||||||
"github.com/vulcanize/vulcanizedb/pkg/fakes"
|
"github.com/vulcanize/vulcanizedb/pkg/fakes"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Fetcher struct {
|
type Fetcher struct {
|
||||||
@ -28,6 +31,8 @@ type Fetcher struct {
|
|||||||
FetchedBlocks []int64
|
FetchedBlocks []int64
|
||||||
BlockChain core.BlockChain
|
BlockChain core.BlockChain
|
||||||
supply big.Int
|
supply big.Int
|
||||||
|
balance map[string]*big.Int
|
||||||
|
allowance map[string]map[string]*big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fetcher) SetSupply(supply string) {
|
func (f *Fetcher) SetSupply(supply string) {
|
||||||
@ -38,69 +43,203 @@ func (f Fetcher) GetBlockChain() core.BlockChain {
|
|||||||
return f.BlockChain
|
return f.BlockChain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Fetcher) FetchSupplyOf(contractAbi string, contractAddress string, blockNumber int64) (big.Int, error) {
|
func (f *Fetcher) FetchBigInt(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) {
|
||||||
|
|
||||||
f.Abi = contractAbi
|
f.Abi = contractAbi
|
||||||
f.ContractAddress = contractAddress
|
f.ContractAddress = contractAddress
|
||||||
f.FetchedBlocks = append(f.FetchedBlocks, blockNumber)
|
f.FetchedBlocks = append(f.FetchedBlocks, blockNumber)
|
||||||
|
|
||||||
accumulator := big.NewInt(1)
|
accumulator := big.NewInt(1)
|
||||||
f.supply.Add(&f.supply, accumulator)
|
|
||||||
|
|
||||||
return f.supply, nil
|
if method == "totalSupply" {
|
||||||
|
f.supply.Add(&f.supply, accumulator)
|
||||||
|
|
||||||
|
return f.supply, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if method == "balanceOf" {
|
||||||
|
rfl := reflect.ValueOf(methodArgs).Field(0)
|
||||||
|
tokenHolderAddr := rfl.Interface().(string)
|
||||||
|
pnt := f.balance[tokenHolderAddr]
|
||||||
|
f.balance[tokenHolderAddr].Add(pnt, accumulator)
|
||||||
|
|
||||||
|
return *f.balance[tokenHolderAddr], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if method == "allowance" {
|
||||||
|
rfl1 := reflect.ValueOf(methodArgs).Field(0)
|
||||||
|
rfl2 := reflect.ValueOf(methodArgs).Field(1)
|
||||||
|
tokenHolderAddr := rfl1.Interface().(string)
|
||||||
|
spenderAddr := rfl2.Interface().(string)
|
||||||
|
pnt := f.allowance[tokenHolderAddr][spenderAddr]
|
||||||
|
f.allowance[tokenHolderAddr][spenderAddr].Add(pnt, accumulator)
|
||||||
|
|
||||||
|
return *f.allowance[tokenHolderAddr][spenderAddr], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return *big.NewInt(0), errors.New("invalid method argument")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TotalSupplyRepository struct {
|
func (f *Fetcher) FetchBool(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (bool, error) {
|
||||||
TotalSuppliesCreated []every_block.TokenSupply
|
//TODO: this
|
||||||
MissingBlockNumbers []int64
|
return false, nil
|
||||||
StartingBlock int64
|
|
||||||
EndingBlock int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TotalSupplyRepository) Create(supply every_block.TokenSupply) error {
|
func (f *Fetcher) FetchAddress(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (common.Address, error) {
|
||||||
|
//TODO: this
|
||||||
|
var adr common.Address
|
||||||
|
return adr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ERC20TokenRepository struct {
|
||||||
|
TotalSuppliesCreated []every_block.TokenSupply
|
||||||
|
MissingSupplyBlockNumbers []int64
|
||||||
|
TotalBalancesCreated []every_block.TokenBalance
|
||||||
|
MissingBalanceBlockNumbers []int64
|
||||||
|
TotalAllowancesCreated []every_block.TokenAllowance
|
||||||
|
MissingAllowanceBlockNumbers []int64
|
||||||
|
StartingBlock int64
|
||||||
|
EndingBlock int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *ERC20TokenRepository) CreateSupply(supply every_block.TokenSupply) error {
|
||||||
fr.TotalSuppliesCreated = append(fr.TotalSuppliesCreated, supply)
|
fr.TotalSuppliesCreated = append(fr.TotalSuppliesCreated, supply)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TotalSupplyRepository) MissingBlocks(startingBlock int64, highestBlock int64) ([]int64, error) {
|
func (fr *ERC20TokenRepository) CreateBalance(balance every_block.TokenBalance) error {
|
||||||
fr.StartingBlock = startingBlock
|
fr.TotalBalancesCreated = append(fr.TotalBalancesCreated, balance)
|
||||||
fr.EndingBlock = highestBlock
|
return nil
|
||||||
return fr.MissingBlockNumbers, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *TotalSupplyRepository) SetMissingBlocks(missingBlocks []int64) {
|
func (fr *ERC20TokenRepository) CreateAllowance(allowance every_block.TokenAllowance) error {
|
||||||
fr.MissingBlockNumbers = missingBlocks
|
fr.TotalAllowancesCreated = append(fr.TotalAllowancesCreated, allowance)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *ERC20TokenRepository) MissingSupplyBlocks(startingBlock, highestBlock int64, tokenAddress string) ([]int64, error) {
|
||||||
|
fr.StartingBlock = startingBlock
|
||||||
|
fr.EndingBlock = highestBlock
|
||||||
|
return fr.MissingSupplyBlockNumbers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *ERC20TokenRepository) MissingBalanceBlocks(startingBlock, highestBlock int64, tokenAddress, holderAddress string) ([]int64, error) {
|
||||||
|
fr.StartingBlock = startingBlock
|
||||||
|
fr.EndingBlock = highestBlock
|
||||||
|
return fr.MissingBalanceBlockNumbers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *ERC20TokenRepository) MissingAllowanceBlocks(startingBlock, highestBlock int64, tokenAddress, holderAddress, spenderAddress string) ([]int64, error) {
|
||||||
|
fr.StartingBlock = startingBlock
|
||||||
|
fr.EndingBlock = highestBlock
|
||||||
|
return fr.MissingAllowanceBlockNumbers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *ERC20TokenRepository) SetMissingSupplyBlocks(missingBlocks []int64) {
|
||||||
|
fr.MissingSupplyBlockNumbers = missingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *ERC20TokenRepository) SetMissingBalanceBlocks(missingBlocks []int64) {
|
||||||
|
fr.MissingBalanceBlockNumbers = missingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *ERC20TokenRepository) SetMissingAllowanceBlocks(missingBlocks []int64) {
|
||||||
|
fr.MissingAllowanceBlockNumbers = missingBlocks
|
||||||
}
|
}
|
||||||
|
|
||||||
type FailureRepository struct {
|
type FailureRepository struct {
|
||||||
createFail bool
|
createSupplyFail bool
|
||||||
missingBlocksFail bool
|
createBalanceFail bool
|
||||||
missingBlocksNumbers []int64
|
createAllowanceFail bool
|
||||||
|
missingSupplyBlocksFail bool
|
||||||
|
missingBalanceBlocksFail bool
|
||||||
|
missingAllowanceBlocksFail bool
|
||||||
|
missingSupplyBlocksNumbers []int64
|
||||||
|
missingBalanceBlocksNumbers []int64
|
||||||
|
missingAllowanceBlocksNumbers []int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *FailureRepository) Create(supply every_block.TokenSupply) error {
|
func (fr *FailureRepository) CreateSupply(supply every_block.TokenSupply) error {
|
||||||
if fr.createFail {
|
if fr.createSupplyFail {
|
||||||
return fakes.FakeError
|
return fakes.FakeError
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *FailureRepository) MissingBlocks(startingBlock int64, highestBlock int64) ([]int64, error) {
|
func (fr *FailureRepository) CreateBalance(balance every_block.TokenBalance) error {
|
||||||
if fr.missingBlocksFail {
|
if fr.createBalanceFail {
|
||||||
return []int64{}, fakes.FakeError
|
return fakes.FakeError
|
||||||
} else {
|
} else {
|
||||||
return fr.missingBlocksNumbers, nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *FailureRepository) SetCreateFail(fail bool) {
|
func (fr *FailureRepository) CreateAllowance(allowance every_block.TokenAllowance) error {
|
||||||
fr.createFail = fail
|
if fr.createAllowanceFail {
|
||||||
|
return fakes.FakeError
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *FailureRepository) SetMissingBlocksFail(fail bool) {
|
func (fr *FailureRepository) MissingSupplyBlocks(startingBlock, highestBlock int64, tokenAddress string) ([]int64, error) {
|
||||||
fr.missingBlocksFail = fail
|
if fr.missingSupplyBlocksFail {
|
||||||
|
return []int64{}, fakes.FakeError
|
||||||
|
} else {
|
||||||
|
return fr.missingSupplyBlocksNumbers, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fr *FailureRepository) SetMissingBlocks(missingBlocks []int64) {
|
func (fr *FailureRepository) MissingBalanceBlocks(startingBlock, highestBlock int64, tokenAddress, holderAddress string) ([]int64, error) {
|
||||||
fr.missingBlocksNumbers = missingBlocks
|
if fr.missingBalanceBlocksFail {
|
||||||
|
return []int64{}, fakes.FakeError
|
||||||
|
} else {
|
||||||
|
return fr.missingBalanceBlocksNumbers, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) MissingAllowanceBlocks(startingBlock, highestBlock int64, tokenAddress, holderAddress, spenderAddress string) ([]int64, error) {
|
||||||
|
if fr.missingAllowanceBlocksFail {
|
||||||
|
return []int64{}, fakes.FakeError
|
||||||
|
} else {
|
||||||
|
return fr.missingAllowanceBlocksNumbers, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetCreateSupplyFail(fail bool) {
|
||||||
|
fr.createSupplyFail = fail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetCreateBalanceFail(fail bool) {
|
||||||
|
fr.createBalanceFail = fail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetCreateAllowanceFail(fail bool) {
|
||||||
|
fr.createAllowanceFail = fail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetMissingSupplyBlocksFail(fail bool) {
|
||||||
|
fr.missingSupplyBlocksFail = fail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetMissingBalanceBlocksFail(fail bool) {
|
||||||
|
fr.missingBalanceBlocksFail = fail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetMissingAllowanceBlocksFail(fail bool) {
|
||||||
|
fr.missingAllowanceBlocksFail = fail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetMissingSupplyBlocks(missingBlocks []int64) {
|
||||||
|
fr.missingSupplyBlocksNumbers = missingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetMissingBalanceBlocks(missingBlocks []int64) {
|
||||||
|
fr.missingBalanceBlocksNumbers = missingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *FailureRepository) SetMissingAllowanceBlocks(missingBlocks []int64) {
|
||||||
|
fr.missingAllowanceBlocksNumbers = missingBlocks
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,15 @@ var _ = Describe("Reading contracts", func() {
|
|||||||
|
|
||||||
contract := testing.SampleContract()
|
contract := testing.SampleContract()
|
||||||
var balance = new(big.Int)
|
var balance = new(big.Int)
|
||||||
args := common.HexToHash("0xd26114cd6ee289accf82350c8d8487fedb8a0c07")
|
|
||||||
err = blockChain.FetchContractData(contract.Abi, "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", "balanceOf", args, &balance, 5167471)
|
arg := common.HexToHash("0xd26114cd6ee289accf82350c8d8487fedb8a0c07")
|
||||||
|
hashArgs := []common.Hash{arg}
|
||||||
|
balanceOfArgs := make([]interface{}, len(hashArgs))
|
||||||
|
for i, s := range hashArgs {
|
||||||
|
balanceOfArgs[i] = s
|
||||||
|
}
|
||||||
|
|
||||||
|
err = blockChain.FetchContractData(contract.Abi, "0xd26114cd6ee289accf82350c8d8487fedb8a0c07", "balanceOf", balanceOfArgs, &balance, 5167471)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
expected := new(big.Int)
|
expected := new(big.Int)
|
||||||
expected.SetString("10897295492887612977137", 10)
|
expected.SetString("10897295492887612977137", 10)
|
||||||
|
@ -12,5 +12,5 @@ type BlockChain interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ContractDataFetcher interface {
|
type ContractDataFetcher interface {
|
||||||
FetchContractData(abiJSON string, address string, method string, methodArg interface{}, result interface{}, blockNumber int64) error
|
FetchContractData(abiJSON string, address string, method string, methodArgs []interface{}, result interface{}, blockNumber int64) error
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ type MockBlockChain struct {
|
|||||||
fetchContractDataPassedAbi string
|
fetchContractDataPassedAbi string
|
||||||
fetchContractDataPassedAddress string
|
fetchContractDataPassedAddress string
|
||||||
fetchContractDataPassedMethod string
|
fetchContractDataPassedMethod string
|
||||||
fetchContractDataPassedMethodArg interface{}
|
fetchContractDataPassedMethodArgs []interface{}
|
||||||
fetchContractDataPassedResult interface{}
|
fetchContractDataPassedResult interface{}
|
||||||
fetchContractDataPassedBlockNumber int64
|
fetchContractDataPassedBlockNumber int64
|
||||||
getBlockByNumberErr error
|
getBlockByNumberErr error
|
||||||
@ -43,11 +43,11 @@ func (blockChain *MockBlockChain) GetHeaderByNumber(blockNumber int64) (core.Hea
|
|||||||
return core.Header{BlockNumber: blockNumber}, nil
|
return core.Header{BlockNumber: blockNumber}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (blockChain *MockBlockChain) FetchContractData(abiJSON string, address string, method string, methodArg interface{}, result interface{}, blockNumber int64) error {
|
func (blockChain *MockBlockChain) FetchContractData(abiJSON string, address string, method string, methodArgs []interface{}, result interface{}, blockNumber int64) error {
|
||||||
blockChain.fetchContractDataPassedAbi = abiJSON
|
blockChain.fetchContractDataPassedAbi = abiJSON
|
||||||
blockChain.fetchContractDataPassedAddress = address
|
blockChain.fetchContractDataPassedAddress = address
|
||||||
blockChain.fetchContractDataPassedMethod = method
|
blockChain.fetchContractDataPassedMethod = method
|
||||||
blockChain.fetchContractDataPassedMethodArg = methodArg
|
blockChain.fetchContractDataPassedMethodArgs = methodArgs
|
||||||
blockChain.fetchContractDataPassedResult = result
|
blockChain.fetchContractDataPassedResult = result
|
||||||
blockChain.fetchContractDataPassedBlockNumber = blockNumber
|
blockChain.fetchContractDataPassedBlockNumber = blockNumber
|
||||||
return blockChain.fetchContractDataErr
|
return blockChain.fetchContractDataErr
|
||||||
@ -74,7 +74,7 @@ func (blockChain *MockBlockChain) GetBlockByNumber(blockNumber int64) (core.Bloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle methodArg being nil (can't match nil to nil in Gomega)
|
// TODO: handle methodArg being nil (can't match nil to nil in Gomega)
|
||||||
func (blockChain *MockBlockChain) AssertFetchContractDataCalledWith(abiJSON string, address string, method string, methodArg interface{}, result interface{}, blockNumber int64) {
|
func (blockChain *MockBlockChain) AssertFetchContractDataCalledWith(abiJSON string, address string, method string, methodArgs []interface{}, result interface{}, blockNumber int64) {
|
||||||
Expect(blockChain.fetchContractDataPassedAbi).To(Equal(abiJSON))
|
Expect(blockChain.fetchContractDataPassedAbi).To(Equal(abiJSON))
|
||||||
Expect(blockChain.fetchContractDataPassedAddress).To(Equal(address))
|
Expect(blockChain.fetchContractDataPassedAddress).To(Equal(address))
|
||||||
Expect(blockChain.fetchContractDataPassedMethod).To(Equal(method))
|
Expect(blockChain.fetchContractDataPassedMethod).To(Equal(method))
|
||||||
|
@ -14,14 +14,14 @@ var (
|
|||||||
ErrInvalidStateAttribute = errors.New("invalid state attribute")
|
ErrInvalidStateAttribute = errors.New("invalid state attribute")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (blockChain *BlockChain) FetchContractData(abiJSON string, address string, method string, methodArg interface{}, result interface{}, blockNumber int64) error {
|
func (blockChain *BlockChain) FetchContractData(abiJSON string, address string, method string, methodArgs []interface{}, result interface{}, blockNumber int64) error {
|
||||||
parsed, err := ParseAbi(abiJSON)
|
parsed, err := ParseAbi(abiJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var input []byte
|
var input []byte
|
||||||
if methodArg != nil {
|
if methodArgs != nil {
|
||||||
input, err = parsed.Pack(method, methodArg)
|
input, err = parsed.Pack(method, methodArgs...)
|
||||||
} else {
|
} else {
|
||||||
input, err = parsed.Pack(method)
|
input, err = parsed.Pack(method)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user