2018-05-05 20:25:54 +00:00
|
|
|
// Copyright 2018 Vulcanize
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package every_block
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
|
|
|
|
"log"
|
|
|
|
)
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// Interface definition for a generic ERC20 token repository
|
2018-05-05 20:25:54 +00:00
|
|
|
type ERC20RepositoryInterface interface {
|
2018-08-09 16:58:06 +00:00
|
|
|
CreateSupply(supply TokenSupply) error
|
|
|
|
MissingSupplyBlocks(startingBlock, highestBlock int64, tokenAddress string) ([]int64, error)
|
2018-05-05 20:25:54 +00:00
|
|
|
}
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// Generic ERC20 token Repo struct
|
|
|
|
type ERC20TokenRepository struct {
|
2018-05-05 20:25:54 +00:00
|
|
|
*postgres.DB
|
|
|
|
}
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// Repo error
|
2018-05-05 20:25:54 +00:00
|
|
|
type repositoryError struct {
|
|
|
|
err string
|
|
|
|
msg string
|
|
|
|
blockNumber int64
|
|
|
|
}
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// Repo error method
|
2018-05-05 20:25:54 +00:00
|
|
|
func (re *repositoryError) Error() string {
|
|
|
|
return fmt.Sprintf(re.msg, re.blockNumber, re.err)
|
|
|
|
}
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// Used to create a new Repo error for a given error and fetch method
|
2018-05-05 20:25:54 +00:00
|
|
|
func newRepositoryError(err error, msg string, blockNumber int64) error {
|
|
|
|
e := repositoryError{err.Error(), msg, blockNumber}
|
|
|
|
log.Println(e.Error())
|
|
|
|
return &e
|
|
|
|
}
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// Constant error definitions
|
2018-05-05 20:25:54 +00:00
|
|
|
const (
|
|
|
|
GetBlockError = "Error fetching 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"
|
|
|
|
)
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// 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 {
|
2018-05-05 20:25:54 +00:00
|
|
|
var blockId int
|
|
|
|
err := tsp.DB.Get(&blockId, `SELECT id FROM blocks WHERE number = $1 AND eth_node_id = $2`, supply.BlockNumber, tsp.NodeID)
|
|
|
|
if err != nil {
|
|
|
|
return newRepositoryError(err, GetBlockError, supply.BlockNumber)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = tsp.DB.Exec(
|
|
|
|
`INSERT INTO token_supply (supply, token_address, block_id)
|
|
|
|
VALUES($1, $2, $3)`,
|
|
|
|
supply.Value, supply.TokenAddress, blockId)
|
|
|
|
if err != nil {
|
|
|
|
return newRepositoryError(err, InsertTokenSupplyError, supply.BlockNumber)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
// 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) {
|
2018-05-05 20:25:54 +00:00
|
|
|
blockNumbers := make([]int64, 0)
|
|
|
|
|
|
|
|
err := tsp.DB.Select(
|
|
|
|
&blockNumbers,
|
|
|
|
`SELECT number FROM BLOCKS
|
2018-08-12 20:35:23 +00:00
|
|
|
LEFT JOIN token_supply ON blocks.id = block_id
|
|
|
|
AND token_address = $1
|
2018-05-05 20:25:54 +00:00
|
|
|
WHERE block_id ISNULL
|
2018-08-12 20:35:23 +00:00
|
|
|
AND eth_node_id = $2
|
|
|
|
AND number >= $3
|
|
|
|
AND number <= $4
|
2018-05-05 20:25:54 +00:00
|
|
|
LIMIT 20`,
|
2018-08-12 20:35:23 +00:00
|
|
|
tokenAddress,
|
2018-05-05 20:25:54 +00:00
|
|
|
tsp.NodeID,
|
|
|
|
startingBlock,
|
|
|
|
highestBlock,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return []int64{}, newRepositoryError(err, MissingBlockError, startingBlock)
|
|
|
|
}
|
|
|
|
return blockNumbers, err
|
Moved fetcher to generic directory (methods have to remain public since it is in seperate package now), added FetchHash method, created ERC20 and generic getters which call the fetcher with specific contract methods (GetTotalSupply, GetBalance, GetAllowance for ERC20 getter, and GetOwner, GetStoppedStatus, GetStringName, GetHashName, GetStringSymbol, GetHashSymbol, and GetDecimals for generic getter). Getter tests cover all but GetBalance and GetAllowance, and also cover all of the Fetcher methods- but with only nil methodArgs. GetAllowance and GetBalance tests are not working against infura and these are the only contract method calls with arguments passed in so I suspect this might be where the issue lies. Have tested GetBalance using previous version of FetchContractData without the variadic input to the Pack method and it fails with the same error so I don’t think it is due to those changes.
2018-08-15 04:17:22 +00:00
|
|
|
}
|