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_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
|
|
. "github.com/onsi/gomega"
|
|
|
|
|
|
|
|
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block"
|
|
|
|
"github.com/vulcanize/vulcanizedb/examples/test_helpers"
|
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/core"
|
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
|
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
|
|
|
|
"github.com/vulcanize/vulcanizedb/test_config"
|
|
|
|
"math/rand"
|
|
|
|
)
|
|
|
|
|
2018-08-12 20:35:23 +00:00
|
|
|
var _ = Describe("ERC20 Token Supply Repository", func() {
|
2018-05-05 20:25:54 +00:00
|
|
|
var db *postgres.DB
|
|
|
|
var blockId int64
|
|
|
|
var blockNumber int64
|
2018-08-09 16:58:06 +00:00
|
|
|
var repository every_block.ERC20TokenRepository
|
2018-05-05 20:25:54 +00:00
|
|
|
var blockRepository repositories.BlockRepository
|
|
|
|
testAddress := "abc"
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
|
|
|
db = test_helpers.CreateNewDatabase()
|
2018-08-09 16:58:06 +00:00
|
|
|
repository = every_block.ERC20TokenRepository{DB: db}
|
2018-05-05 20:25:54 +00:00
|
|
|
_, err := db.Query(`DELETE FROM token_supply`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
blockRepository = *repositories.NewBlockRepository(db)
|
|
|
|
blockNumber = rand.Int63()
|
|
|
|
blockId = test_helpers.CreateBlock(blockNumber, blockRepository)
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("Create", func() {
|
|
|
|
It("creates a token supply record", func() {
|
|
|
|
supply := supplyModel(blockNumber, testAddress, "100")
|
2018-08-09 16:58:06 +00:00
|
|
|
err := repository.CreateSupply(supply)
|
2018-05-05 20:25:54 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
dbResult := test_helpers.TokenSupplyDBRow{}
|
|
|
|
expectedTokenSupply := test_helpers.TokenSupplyDBRow{
|
|
|
|
Supply: int64(100),
|
|
|
|
BlockID: blockId,
|
|
|
|
TokenAddress: testAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
var count int
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_supply`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(1))
|
|
|
|
|
|
|
|
err = repository.DB.QueryRowx(`SELECT * FROM token_supply`).StructScan(&dbResult)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(dbResult.Supply).To(Equal(expectedTokenSupply.Supply))
|
|
|
|
Expect(dbResult.BlockID).To(Equal(expectedTokenSupply.BlockID))
|
|
|
|
Expect(dbResult.TokenAddress).To(Equal(expectedTokenSupply.TokenAddress))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("returns an error if fetching the block's id from the database fails", func() {
|
|
|
|
errorSupply := supplyModel(-1, "", "")
|
2018-08-09 16:58:06 +00:00
|
|
|
err := repository.CreateSupply(errorSupply)
|
2018-05-05 20:25:54 +00:00
|
|
|
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
Expect(err.Error()).To(ContainSubstring("sql"))
|
|
|
|
Expect(err.Error()).To(ContainSubstring("block number -1"))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("returns an error if inserting the token_supply fails", func() {
|
|
|
|
errorSupply := supplyModel(blockNumber, "", "")
|
2018-08-09 16:58:06 +00:00
|
|
|
err := repository.CreateSupply(errorSupply)
|
2018-05-05 20:25:54 +00:00
|
|
|
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
Expect(err.Error()).To(ContainSubstring("pq"))
|
|
|
|
Expect(err.Error()).To(ContainSubstring("token_supply for block number"))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("When there are multiple nodes", func() {
|
|
|
|
var node2DB *postgres.DB
|
|
|
|
var node2BlockRepo *repositories.BlockRepository
|
|
|
|
var node2BlockId int64
|
2018-08-09 16:58:06 +00:00
|
|
|
var node2TokenSupplyRepo every_block.ERC20TokenRepository
|
2018-05-05 20:25:54 +00:00
|
|
|
var tokenSupply every_block.TokenSupply
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
|
|
|
node2DB = createDbForAnotherNode()
|
|
|
|
|
|
|
|
//create another block with the same number on node2
|
|
|
|
node2BlockRepo = repositories.NewBlockRepository(node2DB)
|
|
|
|
node2BlockId = test_helpers.CreateBlock(blockNumber, *node2BlockRepo)
|
|
|
|
|
|
|
|
tokenSupply = supplyModel(blockNumber, "abc", "100")
|
2018-08-09 16:58:06 +00:00
|
|
|
node2TokenSupplyRepo = every_block.ERC20TokenRepository{DB: node2DB}
|
2018-05-05 20:25:54 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
It("only creates token_supply records for the current node (node2)", func() {
|
2018-08-09 16:58:06 +00:00
|
|
|
err := node2TokenSupplyRepo.CreateSupply(tokenSupply)
|
2018-05-05 20:25:54 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
var tokenSupplies []test_helpers.TokenSupplyDBRow
|
|
|
|
err = node2TokenSupplyRepo.DB.Select(&tokenSupplies, `SELECT * FROM token_supply`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(tokenSupplies)).To(Equal(1))
|
|
|
|
Expect(tokenSupplies[0].BlockID).To(Equal(node2BlockId))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only includes missing block numbers for the current node", func() {
|
|
|
|
//create token_supply on original node
|
2018-08-09 16:58:06 +00:00
|
|
|
err := repository.CreateSupply(tokenSupply)
|
2018-05-05 20:25:54 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
originalNodeMissingBlocks, err := repository.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
2018-05-05 20:25:54 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(originalNodeMissingBlocks)).To(Equal(0))
|
|
|
|
|
2018-08-09 16:58:06 +00:00
|
|
|
node2MissingBlocks, err := node2TokenSupplyRepo.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
2018-05-05 20:25:54 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(node2MissingBlocks)).To(Equal(1))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("MissingBlocks", func() {
|
|
|
|
It("returns the block numbers for which an associated TokenSupply record hasn't been created", func() {
|
2018-08-12 20:35:23 +00:00
|
|
|
createTokenSupplyFor(repository, blockNumber, testAddress)
|
2018-05-05 20:25:54 +00:00
|
|
|
|
|
|
|
newBlockNumber := blockNumber + 1
|
|
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
2018-08-09 16:58:06 +00:00
|
|
|
blocks, err := repository.MissingSupplyBlocks(blockNumber, newBlockNumber, testAddress)
|
2018-05-05 20:25:54 +00:00
|
|
|
|
|
|
|
Expect(blocks).To(ConsistOf(newBlockNumber))
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only returns blocks within the given range", func() {
|
|
|
|
newBlockNumber := blockNumber + 1
|
|
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
2018-08-09 16:58:06 +00:00
|
|
|
blocks, err := repository.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
2018-05-05 20:25:54 +00:00
|
|
|
|
|
|
|
Expect(blocks).NotTo(ConsistOf(newBlockNumber))
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("does not return numbers that already have an associated TokenSupply record", func() {
|
2018-08-12 20:35:23 +00:00
|
|
|
createTokenSupplyFor(repository, blockNumber, testAddress)
|
2018-08-09 16:58:06 +00:00
|
|
|
blocks, err := repository.MissingSupplyBlocks(blockNumber, blockNumber, testAddress)
|
2018-05-05 20:25:54 +00:00
|
|
|
|
|
|
|
Expect(blocks).To(BeEmpty())
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
It("deletes the token supply record when the associated block is deleted", func() {
|
2018-08-12 20:35:23 +00:00
|
|
|
err := repository.CreateSupply(every_block.TokenSupply{BlockNumber: blockNumber, TokenAddress: testAddress, Value: "0"})
|
2018-05-05 20:25:54 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
var count int
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_supply`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(1))
|
|
|
|
|
|
|
|
_, err = db.Query(`DELETE FROM blocks`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_supply`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(0))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-08-22 18:10:23 +00:00
|
|
|
var _ = Describe("ERC20 Token Balance Repository", func() {
|
|
|
|
var db *postgres.DB
|
|
|
|
var blockId int64
|
|
|
|
var blockNumber int64
|
|
|
|
var repository every_block.ERC20TokenRepository
|
|
|
|
var blockRepository repositories.BlockRepository
|
|
|
|
testTokenAddress := "abc"
|
|
|
|
testHolderAddress := "def"
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
|
|
|
db = test_helpers.CreateNewDatabase()
|
|
|
|
repository = every_block.ERC20TokenRepository{DB: db}
|
|
|
|
_, err := db.Query(`DELETE FROM token_balance`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
blockRepository = *repositories.NewBlockRepository(db)
|
|
|
|
blockNumber = rand.Int63()
|
|
|
|
blockId = test_helpers.CreateBlock(blockNumber, blockRepository)
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("Create", func() {
|
|
|
|
It("creates a token balance record", func() {
|
|
|
|
balance := balanceOfModel(blockNumber, testTokenAddress, testHolderAddress, "100")
|
|
|
|
err := repository.CreateBalance(balance)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
dbResult := test_helpers.TokenBalanceDBRow{}
|
|
|
|
expectedTokenBalance := test_helpers.TokenBalanceDBRow{
|
|
|
|
Balance: int64(100),
|
|
|
|
BlockID: blockId,
|
|
|
|
TokenAddress: testTokenAddress,
|
|
|
|
TokenHolderAddress: testHolderAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
var count int
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_balance`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(1))
|
|
|
|
|
|
|
|
err = repository.DB.QueryRowx(`SELECT * FROM token_balance`).StructScan(&dbResult)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(dbResult.Balance).To(Equal(expectedTokenBalance.Balance))
|
|
|
|
Expect(dbResult.BlockID).To(Equal(expectedTokenBalance.BlockID))
|
|
|
|
Expect(dbResult.TokenAddress).To(Equal(expectedTokenBalance.TokenAddress))
|
|
|
|
Expect(dbResult.TokenHolderAddress).To(Equal(expectedTokenBalance.TokenHolderAddress))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("returns an error if fetching the block's id from the database fails", func() {
|
|
|
|
errorBalance := balanceOfModel(-1, "", "", "")
|
|
|
|
err := repository.CreateBalance(errorBalance)
|
|
|
|
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
Expect(err.Error()).To(ContainSubstring("sql"))
|
|
|
|
Expect(err.Error()).To(ContainSubstring("block number -1"))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("returns an error if inserting the token_balance fails", func() {
|
|
|
|
errorBalance := balanceOfModel(blockNumber, "", "", "")
|
|
|
|
err := repository.CreateBalance(errorBalance)
|
|
|
|
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
Expect(err.Error()).To(ContainSubstring("pq"))
|
|
|
|
Expect(err.Error()).To(ContainSubstring("token_balance for block number"))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("When there are multiple nodes", func() {
|
|
|
|
var node2DB *postgres.DB
|
|
|
|
var node2BlockRepo *repositories.BlockRepository
|
|
|
|
var node2BlockId int64
|
|
|
|
var node2TokenSupplyRepo every_block.ERC20TokenRepository
|
|
|
|
var tokenBalance every_block.TokenBalance
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
|
|
|
node2DB = createDbForAnotherNode()
|
|
|
|
|
|
|
|
//create another block with the same number on node2
|
|
|
|
node2BlockRepo = repositories.NewBlockRepository(node2DB)
|
|
|
|
node2BlockId = test_helpers.CreateBlock(blockNumber, *node2BlockRepo)
|
|
|
|
|
|
|
|
tokenBalance = balanceOfModel(blockNumber, "abc", "def", "100")
|
|
|
|
node2TokenSupplyRepo = every_block.ERC20TokenRepository{DB: node2DB}
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only creates token_balance records for the current node (node2)", func() {
|
|
|
|
err := node2TokenSupplyRepo.CreateBalance(tokenBalance)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
var tokenBalances []test_helpers.TokenBalanceDBRow
|
|
|
|
err = node2TokenSupplyRepo.DB.Select(&tokenBalances, `SELECT * FROM token_balance`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(tokenBalances)).To(Equal(1))
|
|
|
|
Expect(tokenBalances[0].BlockID).To(Equal(node2BlockId))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only includes missing block numbers for the current node", func() {
|
|
|
|
//create token_balance on original node
|
|
|
|
err := repository.CreateBalance(tokenBalance)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
originalNodeMissingBlocks, err := repository.MissingBalanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(originalNodeMissingBlocks)).To(Equal(0))
|
|
|
|
|
|
|
|
node2MissingBlocks, err := node2TokenSupplyRepo.MissingBalanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(node2MissingBlocks)).To(Equal(1))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("MissingBlocks", func() {
|
|
|
|
It("returns the block numbers for which an associated TokenBalance record hasn't been created", func() {
|
|
|
|
createTokenBalanceFor(repository, blockNumber, testTokenAddress, testHolderAddress)
|
|
|
|
|
|
|
|
newBlockNumber := blockNumber + 1
|
|
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
|
|
|
blocks, err := repository.MissingBalanceBlocks(blockNumber, newBlockNumber, testTokenAddress, testHolderAddress)
|
|
|
|
|
|
|
|
Expect(blocks).To(ConsistOf(newBlockNumber))
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only returns blocks within the given range", func() {
|
|
|
|
newBlockNumber := blockNumber + 1
|
|
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
|
|
|
blocks, err := repository.MissingBalanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress)
|
|
|
|
|
|
|
|
Expect(blocks).NotTo(ConsistOf(newBlockNumber))
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("does not return numbers that already have an associated TokenBalance record", func() {
|
|
|
|
createTokenBalanceFor(repository, blockNumber, testTokenAddress, testHolderAddress)
|
|
|
|
blocks, err := repository.MissingBalanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress)
|
|
|
|
|
|
|
|
Expect(blocks).To(BeEmpty())
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
It("deletes the token balance record when the associated block is deleted", func() {
|
|
|
|
err := repository.CreateBalance(every_block.TokenBalance{
|
|
|
|
BlockNumber: blockNumber,
|
|
|
|
TokenAddress: testTokenAddress,
|
|
|
|
TokenHolderAddress: testHolderAddress,
|
|
|
|
Value: "0",
|
|
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
var count int
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_balance`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(1))
|
|
|
|
|
|
|
|
_, err = db.Query(`DELETE FROM blocks`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_balance`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(0))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
var _ = Describe("ERC20 Token Allowance Repository", func() {
|
|
|
|
var db *postgres.DB
|
|
|
|
var blockId int64
|
|
|
|
var blockNumber int64
|
|
|
|
var repository every_block.ERC20TokenRepository
|
|
|
|
var blockRepository repositories.BlockRepository
|
|
|
|
testTokenAddress := "abc"
|
|
|
|
testHolderAddress := "def"
|
|
|
|
testSpenderAddress := "ghi"
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
|
|
|
db = test_helpers.CreateNewDatabase()
|
|
|
|
repository = every_block.ERC20TokenRepository{DB: db}
|
|
|
|
_, err := db.Query(`DELETE FROM token_allowance`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
blockRepository = *repositories.NewBlockRepository(db)
|
|
|
|
blockNumber = rand.Int63()
|
|
|
|
blockId = test_helpers.CreateBlock(blockNumber, blockRepository)
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("Create", func() {
|
|
|
|
It("creates a token balance record", func() {
|
|
|
|
allowance := allowanceModel(blockNumber, testTokenAddress, testHolderAddress, testSpenderAddress, "100")
|
|
|
|
err := repository.CreateAllowance(allowance)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
dbResult := test_helpers.TokenAllowanceDBRow{}
|
|
|
|
expectedTokenAllowance := test_helpers.TokenAllowanceDBRow{
|
|
|
|
Allowance: int64(100),
|
|
|
|
BlockID: blockId,
|
|
|
|
TokenAddress: testTokenAddress,
|
|
|
|
TokenHolderAddress: testHolderAddress,
|
|
|
|
TokenSpenderAddress: testSpenderAddress,
|
|
|
|
}
|
|
|
|
|
|
|
|
var count int
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_allowance`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(1))
|
|
|
|
|
|
|
|
err = repository.DB.QueryRowx(`SELECT * FROM token_allowance`).StructScan(&dbResult)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(dbResult.Allowance).To(Equal(expectedTokenAllowance.Allowance))
|
|
|
|
Expect(dbResult.BlockID).To(Equal(expectedTokenAllowance.BlockID))
|
|
|
|
Expect(dbResult.TokenAddress).To(Equal(expectedTokenAllowance.TokenAddress))
|
|
|
|
Expect(dbResult.TokenHolderAddress).To(Equal(expectedTokenAllowance.TokenHolderAddress))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("returns an error if fetching the block's id from the database fails", func() {
|
|
|
|
errorAllowance := allowanceModel(-1, "", "", "", "")
|
|
|
|
err := repository.CreateAllowance(errorAllowance)
|
|
|
|
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
Expect(err.Error()).To(ContainSubstring("sql"))
|
|
|
|
Expect(err.Error()).To(ContainSubstring("block number -1"))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("returns an error if inserting the token_allowance fails", func() {
|
|
|
|
errorAllowance := allowanceModel(blockNumber, "", "", "", "")
|
|
|
|
err := repository.CreateAllowance(errorAllowance)
|
|
|
|
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
|
|
Expect(err.Error()).To(ContainSubstring("pq"))
|
|
|
|
Expect(err.Error()).To(ContainSubstring("token_allowance for block number"))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("When there are multiple nodes", func() {
|
|
|
|
var node2DB *postgres.DB
|
|
|
|
var node2BlockRepo *repositories.BlockRepository
|
|
|
|
var node2BlockId int64
|
|
|
|
var node2TokenSupplyRepo every_block.ERC20TokenRepository
|
|
|
|
var tokenAllowance every_block.TokenAllowance
|
|
|
|
|
|
|
|
BeforeEach(func() {
|
|
|
|
node2DB = createDbForAnotherNode()
|
|
|
|
|
|
|
|
//create another block with the same number on node2
|
|
|
|
node2BlockRepo = repositories.NewBlockRepository(node2DB)
|
|
|
|
node2BlockId = test_helpers.CreateBlock(blockNumber, *node2BlockRepo)
|
|
|
|
|
|
|
|
tokenAllowance = allowanceModel(blockNumber, "abc", "def", "ghi", "100")
|
|
|
|
node2TokenSupplyRepo = every_block.ERC20TokenRepository{DB: node2DB}
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only creates token_allowance records for the current node (node2)", func() {
|
|
|
|
err := node2TokenSupplyRepo.CreateAllowance(tokenAllowance)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
var tokenAllowances []test_helpers.TokenAllowanceDBRow
|
|
|
|
err = node2TokenSupplyRepo.DB.Select(&tokenAllowances, `SELECT * FROM token_allowance`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(tokenAllowances)).To(Equal(1))
|
|
|
|
Expect(tokenAllowances[0].BlockID).To(Equal(node2BlockId))
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only includes missing block numbers for the current node", func() {
|
|
|
|
//create token_allowance on original node
|
|
|
|
err := repository.CreateAllowance(tokenAllowance)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
originalNodeMissingBlocks, err := repository.MissingAllowanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress, testSpenderAddress)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(originalNodeMissingBlocks)).To(Equal(0))
|
|
|
|
|
|
|
|
node2MissingBlocks, err := node2TokenSupplyRepo.MissingAllowanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress, testSpenderAddress)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(len(node2MissingBlocks)).To(Equal(1))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Describe("MissingBlocks", func() {
|
|
|
|
It("returns the block numbers for which an associated TokenAllowance record hasn't been created", func() {
|
|
|
|
createTokenAllowanceFor(repository, blockNumber, testTokenAddress, testHolderAddress, testSpenderAddress)
|
|
|
|
|
|
|
|
newBlockNumber := blockNumber + 1
|
|
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
|
|
|
blocks, err := repository.MissingAllowanceBlocks(blockNumber, newBlockNumber, testTokenAddress, testHolderAddress, testSpenderAddress)
|
|
|
|
|
|
|
|
Expect(blocks).To(ConsistOf(newBlockNumber))
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("only returns blocks within the given range", func() {
|
|
|
|
newBlockNumber := blockNumber + 1
|
|
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
|
|
|
blocks, err := repository.MissingAllowanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress, testSpenderAddress)
|
|
|
|
|
|
|
|
Expect(blocks).NotTo(ConsistOf(newBlockNumber))
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
|
|
|
|
It("does not return numbers that already have an associated TokenAllowance record", func() {
|
|
|
|
createTokenAllowanceFor(repository, blockNumber, testTokenAddress, testHolderAddress, testSpenderAddress)
|
|
|
|
blocks, err := repository.MissingAllowanceBlocks(blockNumber, blockNumber, testTokenAddress, testHolderAddress, testSpenderAddress)
|
|
|
|
|
|
|
|
Expect(blocks).To(BeEmpty())
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
It("deletes the token balance record when the associated block is deleted", func() {
|
|
|
|
err := repository.CreateAllowance(every_block.TokenAllowance{
|
|
|
|
BlockNumber: blockNumber,
|
|
|
|
TokenAddress: testTokenAddress,
|
|
|
|
TokenHolderAddress: testHolderAddress,
|
|
|
|
TokenSpenderAddress: testSpenderAddress,
|
|
|
|
Value: "0",
|
|
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
var count int
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_allowance`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(1))
|
|
|
|
|
|
|
|
_, err = db.Query(`DELETE FROM blocks`)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_allowance`).Scan(&count)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(count).To(Equal(0))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2018-08-12 20:35:23 +00:00
|
|
|
func supplyModel(blockNumber int64, tokenAddress, supplyValue string) every_block.TokenSupply {
|
2018-05-05 20:25:54 +00:00
|
|
|
return every_block.TokenSupply{
|
|
|
|
Value: supplyValue,
|
|
|
|
TokenAddress: tokenAddress,
|
2018-08-12 20:35:23 +00:00
|
|
|
BlockNumber: blockNumber,
|
2018-05-05 20:25:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-22 18:10:23 +00:00
|
|
|
func balanceOfModel(blockNumber int64, tokenAddress, holderAddress, supplyValue string) every_block.TokenBalance {
|
|
|
|
return every_block.TokenBalance{
|
|
|
|
Value: supplyValue,
|
|
|
|
TokenAddress: tokenAddress,
|
|
|
|
TokenHolderAddress: holderAddress,
|
|
|
|
BlockNumber: blockNumber,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func allowanceModel(blockNumber int64, tokenAddress, holderAddress, spenderAddress, supplyValue string) every_block.TokenAllowance {
|
|
|
|
return every_block.TokenAllowance{
|
|
|
|
Value: supplyValue,
|
|
|
|
TokenAddress: tokenAddress,
|
|
|
|
TokenHolderAddress: holderAddress,
|
|
|
|
TokenSpenderAddress: spenderAddress,
|
|
|
|
BlockNumber: blockNumber,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-12 20:35:23 +00:00
|
|
|
func createTokenSupplyFor(repository every_block.ERC20TokenRepository, blockNumber int64, tokenAddress string) {
|
|
|
|
err := repository.CreateSupply(every_block.TokenSupply{
|
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
|
|
|
BlockNumber: blockNumber,
|
2018-08-12 20:35:23 +00:00
|
|
|
TokenAddress: tokenAddress,
|
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
|
|
|
Value: "0",
|
2018-08-12 20:35:23 +00:00
|
|
|
})
|
2018-05-05 20:25:54 +00:00
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
}
|
|
|
|
|
2018-08-22 18:10:23 +00:00
|
|
|
func createTokenBalanceFor(repository every_block.ERC20TokenRepository, blockNumber int64, tokenAddress, holderAddress string) {
|
|
|
|
err := repository.CreateBalance(every_block.TokenBalance{
|
|
|
|
BlockNumber: blockNumber,
|
|
|
|
TokenAddress: tokenAddress,
|
|
|
|
TokenHolderAddress: holderAddress,
|
|
|
|
Value: "0",
|
|
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
}
|
|
|
|
|
|
|
|
func createTokenAllowanceFor(repository every_block.ERC20TokenRepository, blockNumber int64, tokenAddress, holderAddress, spenderAddress string) {
|
|
|
|
err := repository.CreateAllowance(every_block.TokenAllowance{
|
|
|
|
BlockNumber: blockNumber,
|
|
|
|
TokenAddress: tokenAddress,
|
|
|
|
TokenHolderAddress: holderAddress,
|
|
|
|
TokenSpenderAddress: spenderAddress,
|
|
|
|
Value: "0",
|
|
|
|
})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
}
|
|
|
|
|
2018-05-05 20:25:54 +00:00
|
|
|
func createDbForAnotherNode() *postgres.DB {
|
|
|
|
anotherNode := core.Node{
|
|
|
|
GenesisBlock: "GENESIS",
|
|
|
|
NetworkID: 1,
|
|
|
|
ID: "testNodeId",
|
|
|
|
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
|
|
|
|
}
|
|
|
|
|
|
|
|
return test_config.NewTestDBWithoutDeletingRecords(anotherNode)
|
|
|
|
}
|