From 9b41000b88a0908d51a80e8044d4e0c9fd5bd108 Mon Sep 17 00:00:00 2001 From: Ian Norden Date: Tue, 14 Aug 2018 23:17:22 -0500 Subject: [PATCH] =?UTF-8?q?Moved=20fetcher=20to=20generic=20directory=20(m?= =?UTF-8?q?ethods=20have=20to=20remain=20public=20since=20it=20is=20in=20s?= =?UTF-8?q?eperate=20package=20now),=20added=20FetchHash=20method,=20creat?= =?UTF-8?q?ed=20ERC20=20and=20generic=20getters=20which=20call=20the=20fet?= =?UTF-8?q?cher=20with=20specific=20contract=20methods=20(GetTotalSupply,?= =?UTF-8?q?=20GetBalance,=20GetAllowance=20for=20ERC20=20getter,=20and=20G?= =?UTF-8?q?etOwner,=20GetStoppedStatus,=20GetStringName,=20GetHashName,=20?= =?UTF-8?q?GetStringSymbol,=20GetHashSymbol,=20and=20GetDecimals=20for=20g?= =?UTF-8?q?eneric=20getter).=20Getter=20tests=20cover=20all=20but=20GetBal?= =?UTF-8?q?ance=20and=20GetAllowance,=20and=20also=20cover=20all=20of=20th?= =?UTF-8?q?e=20Fetcher=20methods-=20but=20with=20only=20nil=20methodArgs.?= =?UTF-8?q?=20GetAllowance=20and=20GetBalance=20tests=20are=20not=20workin?= =?UTF-8?q?g=20against=20infura=20and=20these=20are=20the=20only=20contrac?= =?UTF-8?q?t=20method=20calls=20with=20arguments=20passed=20in=20so=20I=20?= =?UTF-8?q?suspect=20this=20might=20be=20where=20the=20issue=20lies.=20Hav?= =?UTF-8?q?e=20tested=20GetBalance=20using=20previous=20version=20of=20Fet?= =?UTF-8?q?chContractData=20without=20the=20variadic=20input=20to=20the=20?= =?UTF-8?q?Pack=20method=20and=20it=20fails=20with=20the=20same=20error=20?= =?UTF-8?q?so=20I=20don=E2=80=99t=20think=20it=20is=20due=20to=20those=20c?= =?UTF-8?q?hanges.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/constants/constants.go | 2 + .../every_block/every_block_suite_test.go | 2 +- .../erc20_watcher/every_block/fetcher_test.go | 176 --------- examples/erc20_watcher/every_block/getter.go | 64 +++ .../erc20_watcher/every_block/getter_test.go | 83 ++++ .../erc20_watcher/every_block/repository.go | 2 +- .../every_block/repository_test.go | 4 +- .../erc20_watcher/every_block/transformer.go | 22 +- .../every_block/transformer_test.go | 40 +- .../every_block/every_block_suite_test.go | 33 ++ examples/generic/every_block/getter.go | 84 ++++ examples/generic/every_block/getter_test.go | 364 ++++++++++++++++++ .../every_block => generic}/fetcher.go | 62 +-- examples/mocks/mocks.go | 140 ++++++- pkg/fakes/mock_blockchain.go | 2 +- 15 files changed, 837 insertions(+), 243 deletions(-) delete mode 100644 examples/erc20_watcher/every_block/fetcher_test.go create mode 100644 examples/erc20_watcher/every_block/getter.go create mode 100644 examples/erc20_watcher/every_block/getter_test.go create mode 100644 examples/generic/every_block/every_block_suite_test.go create mode 100644 examples/generic/every_block/getter.go create mode 100644 examples/generic/every_block/getter_test.go rename examples/{erc20_watcher/every_block => generic}/fetcher.go (63%) diff --git a/examples/constants/constants.go b/examples/constants/constants.go index abc84f94..646f7b29 100644 --- a/examples/constants/constants.go +++ b/examples/constants/constants.go @@ -16,6 +16,8 @@ package constants //Contract Addresses var DaiContractAddress = "0x89d24a6b4ccb1b6faa2625fe562bdd9a23260359" +var TusdContractAddress = "0x8dd5fbCe2F6a956C3022bA3663759011Dd51e73E" //Abis var DaiAbiString = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"name_","type":"bytes32"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"push","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"move","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"start","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"guy","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"wad","type":"uint256"}],"name":"pull","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"symbol_","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"}]` +var TusdAbiString = `[{"constant":true,"inputs":[],"name":"burnMin","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"delegateAllowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"burnFeeFlat","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_canReceiveMintWhiteList","type":"address"},{"name":"_canBurnWhiteList","type":"address"},{"name":"_blackList","type":"address"},{"name":"_noFeesList","type":"address"}],"name":"setLists","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"token","type":"address"}],"name":"reclaimToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newContract","type":"address"}],"name":"delegateToNewContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_transferFeeNumerator","type":"uint80"},{"name":"_transferFeeDenominator","type":"uint80"},{"name":"_mintFeeNumerator","type":"uint80"},{"name":"_mintFeeDenominator","type":"uint80"},{"name":"_mintFeeFlat","type":"uint256"},{"name":"_burnFeeNumerator","type":"uint80"},{"name":"_burnFeeDenominator","type":"uint80"},{"name":"_burnFeeFlat","type":"uint256"}],"name":"changeStakingFees","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"canReceiveMintWhiteList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"delegatedFrom","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"origSender","type":"address"}],"name":"delegateApprove","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"contractAddr","type":"address"}],"name":"reclaimContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allowances","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"delegateBalanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"origSender","type":"address"}],"name":"delegateTransferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"claimOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sheet","type":"address"}],"name":"setBalanceSheet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"},{"name":"origSender","type":"address"}],"name":"delegateIncreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"burnFeeNumerator","outputs":[{"name":"","type":"uint80"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"canBurnWhiteList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"burnMax","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mintFeeDenominator","outputs":[{"name":"","type":"uint80"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"staker","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"setDelegatedFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"noFeesList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newMin","type":"uint256"},{"name":"newMax","type":"uint256"}],"name":"changeBurnBounds","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"delegateTotalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"balances","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"}],"name":"changeName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"mintFeeNumerator","outputs":[{"name":"","type":"uint80"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"transferFeeNumerator","outputs":[{"name":"","type":"uint80"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"},{"name":"origSender","type":"address"}],"name":"delegateDecreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"origSender","type":"address"}],"name":"delegateTransfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"reclaimEther","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newStaker","type":"address"}],"name":"changeStaker","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"wipeBlacklistedAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"from_","type":"address"},{"name":"value_","type":"uint256"},{"name":"data_","type":"bytes"}],"name":"tokenFallback","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"burnFeeDenominator","outputs":[{"name":"","type":"uint80"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"delegate","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"blackList","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"transferFeeDenominator","outputs":[{"name":"","type":"uint80"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"mintFeeFlat","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pendingOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sheet","type":"address"}],"name":"setAllowanceSheet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newMin","type":"uint256"},{"indexed":false,"name":"newMax","type":"uint256"}],"name":"ChangeBurnBoundsEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"},{"indexed":false,"name":"balance","type":"uint256"}],"name":"WipedAccount","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"newContract","type":"address"}],"name":"DelegatedTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}]` diff --git a/examples/erc20_watcher/every_block/every_block_suite_test.go b/examples/erc20_watcher/every_block/every_block_suite_test.go index 61cb9c87..e25398b1 100644 --- a/examples/erc20_watcher/every_block/every_block_suite_test.go +++ b/examples/erc20_watcher/every_block/every_block_suite_test.go @@ -25,7 +25,7 @@ import ( func TestEveryBlock(t *testing.T) { RegisterFailHandler(Fail) - RunSpecs(t, "EveryBlock Suite") + RunSpecs(t, "ERC20 EveryBlock Suite") } var _ = BeforeSuite(func() { diff --git a/examples/erc20_watcher/every_block/fetcher_test.go b/examples/erc20_watcher/every_block/fetcher_test.go deleted file mode 100644 index 20a6cdc7..00000000 --- a/examples/erc20_watcher/every_block/fetcher_test.go +++ /dev/null @@ -1,176 +0,0 @@ -// 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 ( - "math/big" - - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rpc" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/vulcanize/vulcanizedb/examples/constants" - "github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block" - "github.com/vulcanize/vulcanizedb/pkg/fakes" - "github.com/vulcanize/vulcanizedb/pkg/geth" - "github.com/vulcanize/vulcanizedb/pkg/geth/client" - rpc2 "github.com/vulcanize/vulcanizedb/pkg/geth/converters/rpc" - "github.com/vulcanize/vulcanizedb/pkg/geth/node" - "github.com/ethereum/go-ethereum/common" -) - -var _ = Describe("ERC20 Fetcher", func() { - blockNumber := int64(5502914) - - Describe("totalSupply", func() { - It("fetches total supply data from the blockchain with the correct arguments", func() { - fakeBlockChain := fakes.NewMockBlockChain() - testFetcher := every_block.NewFetcher(fakeBlockChain) - testAbi := "testAbi" - testContractAddress := "testContractAddress" - - _, err := testFetcher.FetchBigInt("totalSupply", testAbi, testContractAddress, blockNumber, nil) - - Expect(err).NotTo(HaveOccurred()) - expectedResult := big.Int{} - expected := &expectedResult - fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "totalSupply", nil, &expected, blockNumber) - }) - - It("fetches dai token's total supply at the given block height", func() { - infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" - rawRpcClient, err := rpc.Dial(infuraIPC) - Expect(err).NotTo(HaveOccurred()) - rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) - ethClient := ethclient.NewClient(rawRpcClient) - blockChainClient := client.NewEthClient(ethClient) - node := node.MakeNode(rpcClient) - transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) - blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) - realFetcher := every_block.NewFetcher(blockChain) - result, err := realFetcher.FetchBigInt("totalSupply", constants.DaiAbiString, constants.DaiContractAddress, blockNumber, nil) - - Expect(err).NotTo(HaveOccurred()) - expectedResult := big.Int{} - expectedResult.SetString("27647235749155415536952630", 10) - Expect(result).To(Equal(expectedResult)) - }) - - It("returns an error if the call to the blockchain fails", func() { - blockChain := fakes.NewMockBlockChain() - blockChain.SetFetchContractDataErr(fakes.FakeError) - errorFetcher := every_block.NewFetcher(blockChain) - result, err := errorFetcher.FetchBigInt("totalSupply", "", "", 0, nil) - - Expect(result.String()).To(Equal("0")) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("totalSupply")) - Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) - }) - }) - - Describe("stopped", func() { - It("checks whether or not the contract has been stopped", func() { - fakeBlockChain := fakes.NewMockBlockChain() - testFetcher := every_block.NewFetcher(fakeBlockChain) - testAbi := "testAbi" - testContractAddress := "testContractAddress" - - _, err := testFetcher.FetchBool("stopped", testAbi, testContractAddress, blockNumber, nil) - - Expect(err).NotTo(HaveOccurred()) - var expectedResult bool - expected := &expectedResult - fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "stopped", nil, &expected, blockNumber) - }) - - It("fetches dai token's stopped status at the given block height", func() { - infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" - rawRpcClient, err := rpc.Dial(infuraIPC) - Expect(err).NotTo(HaveOccurred()) - rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) - ethClient := ethclient.NewClient(rawRpcClient) - blockChainClient := client.NewEthClient(ethClient) - node := node.MakeNode(rpcClient) - transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) - blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) - realFetcher := every_block.NewFetcher(blockChain) - result, err := realFetcher.FetchBool("stopped", constants.DaiAbiString, constants.DaiContractAddress, blockNumber, nil) - - Expect(err).NotTo(HaveOccurred()) - Expect(result).To(Equal(false)) - }) - - It("returns an error if the call to the blockchain fails", func() { - blockChain := fakes.NewMockBlockChain() - blockChain.SetFetchContractDataErr(fakes.FakeError) - errorFetcher := every_block.NewFetcher(blockChain) - result, err := errorFetcher.FetchBool("stopped", "", "", 0, nil) - - Expect(result).To(Equal(false)) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("stopped")) - Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) - }) - }) - - Describe("owner", func() { - It("checks what the contract's owner address is", func() { - fakeBlockChain := fakes.NewMockBlockChain() - testFetcher := every_block.NewFetcher(fakeBlockChain) - testAbi := "testAbi" - testContractAddress := "testContractAddress" - - _, err := testFetcher.FetchAddress("owner", testAbi, testContractAddress, blockNumber, nil) - - Expect(err).NotTo(HaveOccurred()) - var expectedResult common.Address - expected := &expectedResult - fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "owner", nil, &expected, blockNumber) - }) - - It("fetches dai token's owner address at the given block height", func() { - infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" - rawRpcClient, err := rpc.Dial(infuraIPC) - Expect(err).NotTo(HaveOccurred()) - rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) - ethClient := ethclient.NewClient(rawRpcClient) - blockChainClient := client.NewEthClient(ethClient) - node := node.MakeNode(rpcClient) - transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) - blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) - realFetcher := every_block.NewFetcher(blockChain) - result, err := realFetcher.FetchAddress("owner", constants.DaiAbiString, constants.DaiContractAddress, blockNumber, nil) - - Expect(err).NotTo(HaveOccurred()) - expectedResult := common.HexToAddress("0x0000000000000000000000000000000000000000") - Expect(result).To(Equal(expectedResult)) - }) - - It("returns an error if the call to the blockchain fails", func() { - blockChain := fakes.NewMockBlockChain() - blockChain.SetFetchContractDataErr(fakes.FakeError) - errorFetcher := every_block.NewFetcher(blockChain) - result, err := errorFetcher.FetchAddress("owner", "", "", 0, nil) - - expectedResult := new(common.Address) - Expect(result).To(Equal(*expectedResult)) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("owner")) - Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) - }) - }) -}) \ No newline at end of file diff --git a/examples/erc20_watcher/every_block/getter.go b/examples/erc20_watcher/every_block/getter.go new file mode 100644 index 00000000..52c02d9d --- /dev/null +++ b/examples/erc20_watcher/every_block/getter.go @@ -0,0 +1,64 @@ +// 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 og 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 Og ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package every_block + +import ( + "math/big" + + "github.com/vulcanize/vulcanizedb/examples/generic" + "github.com/vulcanize/vulcanizedb/pkg/core" +) + +// Getter serves as a higher level data fetcher that invokes its underlying Fetcher methods for a given contract method + +// Interface definition for a Getter +type ERC20GetterInterface interface { + GetTotalSupply(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) + GetBalance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) + GetAllowance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) + GetBlockChain() core.BlockChain +} + +// Getter struct +type Getter struct { + fetcher generic.Fetcher +} + +// Initializes and returns a Getter with the given blockchain +func NewGetter(blockChain core.BlockChain) Getter { + return Getter{ + fetcher: generic.Fetcher{ + BlockChain: blockChain, + }, + } +} + +// Public getter methods for calling contract methods +func (g Getter) GetTotalSupply(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) { + return g.fetcher.FetchBigInt("totalSupply", contractAbi, contractAddress, blockNumber, nil) +} + +func (g Getter) GetBalance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) { + return g.fetcher.FetchBigInt("balanceOf", contractAbi, contractAddress, blockNumber, methodArgs) +} + +func (g Getter) GetAllowance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) { + return g.fetcher.FetchBigInt("allowance", contractAbi, contractAddress, blockNumber, methodArgs) +} + +// Method to retrieve the Getter's blockchain +func (g Getter) GetBlockChain() core.BlockChain { + return g.fetcher.BlockChain +} diff --git a/examples/erc20_watcher/every_block/getter_test.go b/examples/erc20_watcher/every_block/getter_test.go new file mode 100644 index 00000000..a6447811 --- /dev/null +++ b/examples/erc20_watcher/every_block/getter_test.go @@ -0,0 +1,83 @@ +// 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 ( + "math/big" + + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/vulcanize/vulcanizedb/examples/constants" + "github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block" + "github.com/vulcanize/vulcanizedb/pkg/fakes" + "github.com/vulcanize/vulcanizedb/pkg/geth" + "github.com/vulcanize/vulcanizedb/pkg/geth/client" + rpc2 "github.com/vulcanize/vulcanizedb/pkg/geth/converters/rpc" + "github.com/vulcanize/vulcanizedb/pkg/geth/node" +) + +var _ = Describe("ERC20 Getter", func() { + blockNumber := int64(5502914) + + Describe("totalSupply", func() { + It("gets total supply data from the blockchain with the correct arguments", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetTotalSupply(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := big.Int{} + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "totalSupply", nil, &expected, blockNumber) + }) + + It("gets dai token's total supply at the given block height", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetTotalSupply(constants.DaiAbiString, constants.DaiContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := big.Int{} + expectedResult.SetString("27647235749155415536952630", 10) + Expect(result).To(Equal(expectedResult)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetTotalSupply("", "", 0) + + Expect(result.String()).To(Equal("0")) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("totalSupply")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) +}) diff --git a/examples/erc20_watcher/every_block/repository.go b/examples/erc20_watcher/every_block/repository.go index 43c96e3b..61b62f72 100644 --- a/examples/erc20_watcher/every_block/repository.go +++ b/examples/erc20_watcher/every_block/repository.go @@ -99,4 +99,4 @@ func (tsp *ERC20TokenRepository) MissingSupplyBlocks(startingBlock, highestBlock return []int64{}, newRepositoryError(err, MissingBlockError, startingBlock) } return blockNumbers, err -} \ No newline at end of file +} diff --git a/examples/erc20_watcher/every_block/repository_test.go b/examples/erc20_watcher/every_block/repository_test.go index 3d4047ed..e6ed2136 100644 --- a/examples/erc20_watcher/every_block/repository_test.go +++ b/examples/erc20_watcher/every_block/repository_test.go @@ -192,9 +192,9 @@ func supplyModel(blockNumber int64, tokenAddress, supplyValue string) every_bloc func createTokenSupplyFor(repository every_block.ERC20TokenRepository, blockNumber int64, tokenAddress string) { err := repository.CreateSupply(every_block.TokenSupply{ - BlockNumber: blockNumber, + BlockNumber: blockNumber, TokenAddress: tokenAddress, - Value: "0", + Value: "0", }) Expect(err).NotTo(HaveOccurred()) } diff --git a/examples/erc20_watcher/every_block/transformer.go b/examples/erc20_watcher/every_block/transformer.go index 41a47c5c..5dcb90eb 100644 --- a/examples/erc20_watcher/every_block/transformer.go +++ b/examples/erc20_watcher/every_block/transformer.go @@ -25,7 +25,7 @@ import ( ) type Transformer struct { - Fetcher ERC20FetcherInterface + Getter ERC20GetterInterface Repository ERC20RepositoryInterface Config erc20_watcher.ContractConfig } @@ -38,11 +38,11 @@ type TokenSupplyTransformerInitializer struct { Config erc20_watcher.ContractConfig } -func (i TokenSupplyTransformerInitializer) NewTokenSupplyTransformer(db *postgres.DB, blockchain core.BlockChain) shared.Transformer { - fetcher := NewFetcher(blockchain) +func (i TokenSupplyTransformerInitializer) NewTokenSupplyTransformer(db *postgres.DB, blockChain core.BlockChain) shared.Transformer { + getter := NewGetter(blockChain) repository := ERC20TokenRepository{DB: db} transformer := Transformer{ - Fetcher: &fetcher, + Getter: &getter, Repository: &repository, Config: i.Config, } @@ -51,8 +51,8 @@ func (i TokenSupplyTransformerInitializer) NewTokenSupplyTransformer(db *postgre } const ( - FetchingBlocksError = "Error fetching missing blocks starting at block number %d: %s" - FetchingSupplyError = "Error fetching supply for block %d: %s" + FetchingBlocksError = "Error getting missing blocks starting at block number %d: %s" + GetSupplyError = "Error getting supply for block %d: %s" CreateSupplyError = "Error inserting token_supply for block %d: %s" ) @@ -74,8 +74,8 @@ func newTransformerError(err error, blockNumber int64, msg string) error { func (t Transformer) Execute() error { var upperBoundBlock int64 - blockchain := t.Fetcher.GetBlockChain() - lastBlock := blockchain.LastBlock().Int64() + blockChain := t.Getter.GetBlockChain() + lastBlock := blockChain.LastBlock().Int64() if t.Config.LastBlock == -1 { upperBoundBlock = lastBlock @@ -93,14 +93,14 @@ func (t Transformer) Execute() error { } // Fetch supply for missing blocks - log.Printf("Fetching totalSupply for %d blocks", len(blocks)) + log.Printf("Gets 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 { - totalSupply, err := t.Fetcher.FetchBigInt("totalSupply", t.Config.Abi, t.Config.Address, blockNumber, nil) + totalSupply, err := t.Getter.GetTotalSupply(t.Config.Abi, t.Config.Address, blockNumber) if err != nil { - return newTransformerError(err, blockNumber, FetchingSupplyError) + return newTransformerError(err, blockNumber, GetSupplyError) } // Create the supply model model := createTokenSupplyModel(totalSupply, t.Config.Address, blockNumber) diff --git a/examples/erc20_watcher/every_block/transformer_test.go b/examples/erc20_watcher/every_block/transformer_test.go index 242c911f..5c0b1bc7 100644 --- a/examples/erc20_watcher/every_block/transformer_test.go +++ b/examples/erc20_watcher/every_block/transformer_test.go @@ -38,7 +38,7 @@ var testContractConfig = erc20_watcher.ContractConfig{ var config = testContractConfig var _ = Describe("Everyblock transformer", func() { - var fetcher mocks.Fetcher + var getter mocks.Getter var repository mocks.ERC20TokenRepository var transformer every_block.Transformer var blockChain *fakes.MockBlockChain @@ -51,14 +51,14 @@ var _ = Describe("Everyblock transformer", func() { BeforeEach(func() { blockChain = fakes.NewMockBlockChain() blockChain.SetLastBlock(&defaultLastBlock) - fetcher = mocks.Fetcher{BlockChain: blockChain} - fetcher.SetSupply(initialSupply) + getter = mocks.NewGetter(blockChain) + getter.Fetcher.SetSupply(initialSupply) repository = mocks.ERC20TokenRepository{} repository.SetMissingSupplyBlocks([]int64{config.FirstBlock}) //setting the mock repository to return the first block as the missing blocks transformer = every_block.Transformer{ - Fetcher: &fetcher, + Getter: &getter, Repository: &repository, } transformer.SetConfiguration(config) @@ -68,10 +68,10 @@ var _ = Describe("Everyblock transformer", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(len(fetcher.FetchedBlocks)).To(Equal(1)) - Expect(fetcher.FetchedBlocks).To(ConsistOf(config.FirstBlock)) - Expect(fetcher.Abi).To(Equal(config.Abi)) - Expect(fetcher.ContractAddress).To(Equal(config.Address)) + Expect(len(getter.Fetcher.FetchedBlocks)).To(Equal(1)) + Expect(getter.Fetcher.FetchedBlocks).To(ConsistOf(config.FirstBlock)) + Expect(getter.Fetcher.Abi).To(Equal(config.Abi)) + Expect(getter.Fetcher.ContractAddress).To(Equal(config.Address)) Expect(repository.StartingBlock).To(Equal(config.FirstBlock)) Expect(repository.EndingBlock).To(Equal(config.LastBlock)) @@ -93,10 +93,10 @@ var _ = Describe("Everyblock transformer", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(len(fetcher.FetchedBlocks)).To(Equal(3)) - Expect(fetcher.FetchedBlocks).To(ConsistOf(config.FirstBlock, config.FirstBlock+1, config.FirstBlock+2)) - Expect(fetcher.Abi).To(Equal(config.Abi)) - Expect(fetcher.ContractAddress).To(Equal(config.Address)) + Expect(len(getter.Fetcher.FetchedBlocks)).To(Equal(3)) + Expect(getter.Fetcher.FetchedBlocks).To(ConsistOf(config.FirstBlock, config.FirstBlock+1, config.FirstBlock+2)) + Expect(getter.Fetcher.Abi).To(Equal(config.Abi)) + Expect(getter.Fetcher.ContractAddress).To(Equal(config.Address)) Expect(len(repository.TotalSuppliesCreated)).To(Equal(3)) Expect(repository.TotalSuppliesCreated[0].Value).To(Equal(initialSupplyPlusOne)) @@ -110,9 +110,9 @@ var _ = Describe("Everyblock transformer", func() { err := transformer.Execute() Expect(err).NotTo(HaveOccurred()) - Expect(fetcher.FetchedBlocks).To(ConsistOf(testContractConfig.FirstBlock)) - Expect(fetcher.Abi).To(Equal(testContractConfig.Abi)) - Expect(fetcher.ContractAddress).To(Equal(testContractConfig.Address)) + Expect(getter.Fetcher.FetchedBlocks).To(ConsistOf(testContractConfig.FirstBlock)) + Expect(getter.Fetcher.Abi).To(Equal(testContractConfig.Abi)) + Expect(getter.Fetcher.ContractAddress).To(Equal(testContractConfig.Address)) Expect(repository.StartingBlock).To(Equal(testContractConfig.FirstBlock)) Expect(repository.EndingBlock).To(Equal(testContractConfig.LastBlock)) @@ -146,22 +146,22 @@ var _ = Describe("Everyblock transformer", func() { failureRepository := mocks.FailureRepository{} failureRepository.SetMissingSupplyBlocksFail(true) transformer = every_block.Transformer{ - Fetcher: &fetcher, + Getter: &getter, Repository: &failureRepository, } err := transformer.Execute() Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) - Expect(err.Error()).To(ContainSubstring("fetching missing blocks")) + Expect(err.Error()).To(ContainSubstring("getting missing blocks")) }) It("returns an error if the call to the blockChain fails", func() { failureBlockchain := fakes.NewMockBlockChain() failureBlockchain.SetLastBlock(&defaultLastBlock) failureBlockchain.SetFetchContractDataErr(fakes.FakeError) - fetcher := every_block.NewFetcher(failureBlockchain) + getter := every_block.NewGetter(failureBlockchain) transformer = every_block.Transformer{ - Fetcher: &fetcher, + Getter: &getter, Repository: &repository, } err := transformer.Execute() @@ -176,7 +176,7 @@ var _ = Describe("Everyblock transformer", func() { failureRepository.SetCreateSupplyFail(true) transformer = every_block.Transformer{ - Fetcher: &fetcher, + Getter: &getter, Repository: &failureRepository, } err := transformer.Execute() diff --git a/examples/generic/every_block/every_block_suite_test.go b/examples/generic/every_block/every_block_suite_test.go new file mode 100644 index 00000000..daf68e25 --- /dev/null +++ b/examples/generic/every_block/every_block_suite_test.go @@ -0,0 +1,33 @@ +// 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 ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "io/ioutil" + "log" +) + +func TestEveryBlock(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Generic EveryBlock Suite") +} + +var _ = BeforeSuite(func() { + log.SetOutput(ioutil.Discard) +}) diff --git a/examples/generic/every_block/getter.go b/examples/generic/every_block/getter.go new file mode 100644 index 00000000..ec06de9a --- /dev/null +++ b/examples/generic/every_block/getter.go @@ -0,0 +1,84 @@ +// 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 ( + "github.com/ethereum/go-ethereum/common" + "github.com/vulcanize/vulcanizedb/examples/generic" + "github.com/vulcanize/vulcanizedb/pkg/core" + "math/big" +) + +// Getter serves as a higher level data fetcher that invokes its underlying Fetcher methods for a given contract method + +// Interface definition for a Getter +type GenericGetterInterface interface { + GetOwner(contractAbi, contractAddress string, blockNumber int64) (common.Address, error) + GetStoppedStatus(contractAbi, contractAddress string, blockNumber int64) (bool, error) + GetStringName(contractAbi, contractAddress string, blockNumber int64) (string, error) + GetHashName(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) + GetStringSymbol(contractAbi, contractAddress string, blockNumber int64) (string, error) + GetHashSymbol(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) + GetDecimals(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) + GetBlockChain() core.BlockChain +} + +// Getter struct +type Getter struct { + fetcher generic.Fetcher // Underlying Fetcher +} + +// Initializes and returns a Getter with the given blockchain +func NewGetter(blockChain core.BlockChain) Getter { + return Getter{ + fetcher: generic.Fetcher{ + BlockChain: blockChain, + }, + } +} + +// Public getter methods for calling contract methods +func (g Getter) GetOwner(contractAbi, contractAddress string, blockNumber int64) (common.Address, error) { + return g.fetcher.FetchAddress("owner", contractAbi, contractAddress, blockNumber, nil) +} + +func (g Getter) GetStoppedStatus(contractAbi, contractAddress string, blockNumber int64) (bool, error) { + return g.fetcher.FetchBool("stopped", contractAbi, contractAddress, blockNumber, nil) +} + +func (g Getter) GetStringName(contractAbi, contractAddress string, blockNumber int64) (string, error) { + return g.fetcher.FetchString("name", contractAbi, contractAddress, blockNumber, nil) +} + +func (g Getter) GetHashName(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) { + return g.fetcher.FetchHash("name", contractAbi, contractAddress, blockNumber, nil) +} + +func (g Getter) GetStringSymbol(contractAbi, contractAddress string, blockNumber int64) (string, error) { + return g.fetcher.FetchString("symbol", contractAbi, contractAddress, blockNumber, nil) +} + +func (g Getter) GetHashSymbol(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) { + return g.fetcher.FetchHash("symbol", contractAbi, contractAddress, blockNumber, nil) +} + +func (g Getter) GetDecimals(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) { + return g.fetcher.FetchBigInt("decimals", contractAbi, contractAddress, blockNumber, nil) +} + +// Method to retrieve the Getter's blockchain +func (g Getter) GetBlockChain() core.BlockChain { + return g.fetcher.BlockChain +} diff --git a/examples/generic/every_block/getter_test.go b/examples/generic/every_block/getter_test.go new file mode 100644 index 00000000..3251c053 --- /dev/null +++ b/examples/generic/every_block/getter_test.go @@ -0,0 +1,364 @@ +// 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/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/ethereum/go-ethereum/common" + "github.com/vulcanize/vulcanizedb/examples/constants" + "github.com/vulcanize/vulcanizedb/examples/generic/every_block" + "github.com/vulcanize/vulcanizedb/pkg/fakes" + "github.com/vulcanize/vulcanizedb/pkg/geth" + "github.com/vulcanize/vulcanizedb/pkg/geth/client" + rpc2 "github.com/vulcanize/vulcanizedb/pkg/geth/converters/rpc" + "github.com/vulcanize/vulcanizedb/pkg/geth/node" + "math/big" +) + +var _ = Describe("every_block Getter", func() { + blockNumber := int64(5502914) + + Describe("stopped", func() { + It("checks whether or not the contract has been stopped", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetStoppedStatus(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + var expectedResult bool + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "stopped", nil, &expected, blockNumber) + }) + + It("gets dai token's stopped status at the given block height", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetStoppedStatus(constants.DaiAbiString, constants.DaiContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + Expect(result).To(Equal(false)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetStoppedStatus("", "", 0) + + Expect(result).To(Equal(false)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("stopped")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) + + Describe("owner", func() { + It("checks what the contract's owner address is", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetOwner(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + var expectedResult common.Address + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "owner", nil, &expected, blockNumber) + }) + + It("gets dai token's owner address at the given block height", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetOwner(constants.DaiAbiString, constants.DaiContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := common.HexToAddress("0x0000000000000000000000000000000000000000") + Expect(result).To(Equal(expectedResult)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetOwner("", "", 0) + + expectedResult := new(common.Address) + Expect(result).To(Equal(*expectedResult)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("owner")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) + + Describe("hash name", func() { + It("checks the contract's name", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetHashName(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + var expectedResult common.Hash + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "name", nil, &expected, blockNumber) + }) + + It("gets dai token's name at the given blockheight", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetHashName(constants.DaiAbiString, constants.DaiContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := common.HexToHash("0x44616920537461626c65636f696e2076312e3000000000000000000000000000") + Expect(result).To(Equal(expectedResult)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetHashName("", "", 0) + + expectedResult := new(common.Hash) + Expect(result).To(Equal(*expectedResult)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("name")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) + + Describe("hash symbol", func() { + It("checks the contract's symbol", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetHashSymbol(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + var expectedResult common.Hash + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "symbol", nil, &expected, blockNumber) + }) + + It("gets dai token's symbol at the given blockheight", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetHashSymbol(constants.DaiAbiString, constants.DaiContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := common.HexToHash("0x4441490000000000000000000000000000000000000000000000000000000000") + Expect(result).To(Equal(expectedResult)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetHashSymbol("", "", 0) + + expectedResult := new(common.Hash) + Expect(result).To(Equal(*expectedResult)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("symbol")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) + + Describe("decimals", func() { + It("checks what the token's number of decimals", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetDecimals(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + var expectedResult big.Int + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "decimals", nil, &expected, blockNumber) + }) + + It("gets dai token's number of decimals at the given block height", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetDecimals(constants.DaiAbiString, constants.DaiContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := big.Int{} + expectedResult.SetString("18", 10) + Expect(result).To(Equal(expectedResult)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetDecimals("", "", 0) + + expectedResult := new(big.Int) + Expect(result).To(Equal(*expectedResult)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("decimals")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) + + Describe("string name", func() { + It("checks the contract's name", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetStringName(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + var expectedResult string + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "name", nil, &expected, blockNumber) + }) + + It("gets tusd token's name at the given blockheight", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetStringName(constants.TusdAbiString, constants.TusdContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := "TrueUSD" + Expect(result).To(Equal(expectedResult)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetStringName("", "", 0) + + expectedResult := new(string) + Expect(result).To(Equal(*expectedResult)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("name")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) + + Describe("string symbol", func() { + It("checks the contract's symbol", func() { + fakeBlockChain := fakes.NewMockBlockChain() + testGetter := every_block.NewGetter(fakeBlockChain) + testAbi := "testAbi" + testContractAddress := "testContractAddress" + + _, err := testGetter.GetStringSymbol(testAbi, testContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + var expectedResult string + expected := &expectedResult + fakeBlockChain.AssertFetchContractDataCalledWith(testAbi, testContractAddress, "symbol", nil, &expected, blockNumber) + }) + + It("gets tusd token's symbol at the given blockheight", func() { + infuraIPC := "https://mainnet.infura.io/v3/b09888c1113640cc9ab42750ce750c05" + rawRpcClient, err := rpc.Dial(infuraIPC) + Expect(err).NotTo(HaveOccurred()) + rpcClient := client.NewRpcClient(rawRpcClient, infuraIPC) + ethClient := ethclient.NewClient(rawRpcClient) + blockChainClient := client.NewEthClient(ethClient) + node := node.MakeNode(rpcClient) + transactionConverter := rpc2.NewRpcTransactionConverter(ethClient) + blockChain := geth.NewBlockChain(blockChainClient, node, transactionConverter) + realGetter := every_block.NewGetter(blockChain) + result, err := realGetter.GetStringName(constants.TusdAbiString, constants.TusdContractAddress, blockNumber) + + Expect(err).NotTo(HaveOccurred()) + expectedResult := "TrueUSD" + Expect(result).To(Equal(expectedResult)) + }) + + It("returns an error if the call to the blockchain fails", func() { + blockChain := fakes.NewMockBlockChain() + blockChain.SetFetchContractDataErr(fakes.FakeError) + errorGetter := every_block.NewGetter(blockChain) + result, err := errorGetter.GetStringSymbol("", "", 0) + + expectedResult := new(string) + Expect(result).To(Equal(*expectedResult)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("symbol")) + Expect(err.Error()).To(ContainSubstring(fakes.FakeError.Error())) + }) + }) +}) diff --git a/examples/erc20_watcher/every_block/fetcher.go b/examples/generic/fetcher.go similarity index 63% rename from examples/erc20_watcher/every_block/fetcher.go rename to examples/generic/fetcher.go index 0d31fdf6..3417323d 100644 --- a/examples/erc20_watcher/every_block/fetcher.go +++ b/examples/generic/fetcher.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package every_block +package generic import ( "fmt" @@ -23,26 +23,28 @@ import ( "github.com/vulcanize/vulcanizedb/pkg/core" ) +// Fetcher serves as the lower level data fetcher that calls the underlying +// blockchain's FetchConctractData method for a given return type + // Interface definition for a Fetcher -type ERC20FetcherInterface interface { +type FetcherInterface interface { 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 + FetchString(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (string, error) + FetchHash(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (common.Hash, error) } -// Initializes and returns a Fetcher with the given blockchain -func NewFetcher(blockChain core.BlockChain) Fetcher { - return Fetcher{ - BlockChain: blockChain, - } +// Used to create a new Fetcher error for a given error and fetch method +func newFetcherError(err error, fetchMethod string) *fetcherError { + e := fetcherError{err.Error(), fetchMethod} + log.Println(e.Error()) + return &e } // Fetcher struct type Fetcher struct { - BlockChain core.BlockChain - ContractAbi string - ContractAddress string + BlockChain core.BlockChain // Underyling Blockchain } // Fetcher error @@ -56,14 +58,9 @@ func (fe *fetcherError) Error() string { 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 { - e := fetcherError{err.Error(), fetchMethod} - log.Println(e.Error()) - return &e -} +// Generic Fetcher methods used by Getters to call contract methods -// Method used to fetch big.Int result from contract +// Method used to fetch big.Int value from contract func (f Fetcher) FetchBigInt(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) { var result = new(big.Int) err := f.BlockChain.FetchContractData(contractAbi, contractAddress, method, methodArgs, &result, blockNumber) @@ -75,7 +72,7 @@ func (f Fetcher) FetchBigInt(method, contractAbi, contractAddress string, blockN return *result, nil } -// Method used to fetch bool result from contract +// Method used to fetch bool value from contract 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) @@ -87,7 +84,7 @@ func (f Fetcher) FetchBool(method, contractAbi, contractAddress string, blockNum return *result, nil } -// Method used to fetch address result from contract +// Method used to fetch address value 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) @@ -99,7 +96,26 @@ func (f Fetcher) FetchAddress(method, contractAbi, contractAddress string, block return *result, nil } -// Getter method for Fetcher's blockchain -func (f Fetcher) GetBlockChain() core.BlockChain { - return f.BlockChain +// Method used to fetch string value from contract +func (f Fetcher) FetchString(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (string, error) { + var result = new(string) + 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 hash value from contract +func (f Fetcher) FetchHash(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (common.Hash, error) { + var result = new(common.Hash) + err := f.BlockChain.FetchContractData(contractAbi, contractAddress, method, methodArgs, &result, blockNumber) + + if err != nil { + return *result, newFetcherError(err, method) + } + + return *result, nil } diff --git a/examples/mocks/mocks.go b/examples/mocks/mocks.go index 03861de0..063310b1 100644 --- a/examples/mocks/mocks.go +++ b/examples/mocks/mocks.go @@ -33,6 +33,12 @@ type Fetcher struct { supply big.Int balance map[string]*big.Int allowance map[string]map[string]*big.Int + owner common.Address + stopped bool + stringName string + hashName common.Hash + stringSymbol string + hashSymbol common.Hash } func (f *Fetcher) SetSupply(supply string) { @@ -58,7 +64,7 @@ func (f *Fetcher) FetchBigInt(method, contractAbi, contractAddress string, block } if method == "balanceOf" { - rfl := reflect.ValueOf(methodArgs).Field(0) + rfl := reflect.ValueOf(methodArgs[0]) tokenHolderAddr := rfl.Interface().(string) pnt := f.balance[tokenHolderAddr] f.balance[tokenHolderAddr].Add(pnt, accumulator) @@ -67,8 +73,8 @@ func (f *Fetcher) FetchBigInt(method, contractAbi, contractAddress string, block } if method == "allowance" { - rfl1 := reflect.ValueOf(methodArgs).Field(0) - rfl2 := reflect.ValueOf(methodArgs).Field(1) + rfl1 := reflect.ValueOf(methodArgs[0]) + rfl2 := reflect.ValueOf(methodArgs[1]) tokenHolderAddr := rfl1.Interface().(string) spenderAddr := rfl2.Interface().(string) pnt := f.allowance[tokenHolderAddr][spenderAddr] @@ -82,14 +88,132 @@ func (f *Fetcher) FetchBigInt(method, contractAbi, contractAddress string, block } func (f *Fetcher) FetchBool(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (bool, error) { - //TODO: this - return false, nil + + f.Abi = contractAbi + f.ContractAddress = contractAddress + f.FetchedBlocks = append(f.FetchedBlocks, blockNumber) + + b := true + + if method == "stopped" { + f.stopped = b + + return f.stopped, nil + } + + return false, errors.New("invalid method argument") } func (f *Fetcher) FetchAddress(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (common.Address, error) { - //TODO: this - var adr common.Address - return adr, nil + + f.Abi = contractAbi + f.ContractAddress = contractAddress + f.FetchedBlocks = append(f.FetchedBlocks, blockNumber) + + adr := common.StringToAddress("test_address") + + if method == "owner" { + f.owner = adr + + return f.owner, nil + } + return common.StringToAddress(""), errors.New("invalid method argument") +} + +func (f *Fetcher) FetchString(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (string, error) { + + f.Abi = contractAbi + f.ContractAddress = contractAddress + f.FetchedBlocks = append(f.FetchedBlocks, blockNumber) + + if method == "name" { + f.stringName = "test_name" + + return f.stringName, nil + } + + if method == "symbol" { + f.stringSymbol = "test_symbol" + + return f.stringSymbol, nil + } + return "", errors.New("invalid method argument") +} + +func (f *Fetcher) FetchHash(method, contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (common.Hash, error) { + + f.Abi = contractAbi + f.ContractAddress = contractAddress + f.FetchedBlocks = append(f.FetchedBlocks, blockNumber) + + if method == "name" { + f.hashName = common.StringToHash("test_name") + + return f.hashName, nil + } + + if method == "symbol" { + f.hashSymbol = common.StringToHash("test_symbol") + + return f.hashSymbol, nil + } + return common.StringToHash(""), errors.New("invalid method argument") +} + +type Getter struct { + Fetcher Fetcher +} + +func NewGetter(blockChain core.BlockChain) Getter { + return Getter{ + Fetcher: Fetcher{ + BlockChain: blockChain, + }, + } +} + +func (g *Getter) GetTotalSupply(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) { + return g.Fetcher.FetchBigInt("totalSupply", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetBalance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) { + return g.Fetcher.FetchBigInt("balanceOf", contractAbi, contractAddress, blockNumber, methodArgs) +} + +func (g *Getter) GetAllowance(contractAbi, contractAddress string, blockNumber int64, methodArgs []interface{}) (big.Int, error) { + return g.Fetcher.FetchBigInt("allowance", contractAbi, contractAddress, blockNumber, methodArgs) +} + +func (g *Getter) GetOwner(contractAbi, contractAddress string, blockNumber int64) (common.Address, error) { + return g.Fetcher.FetchAddress("owner", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetStoppedStatus(contractAbi, contractAddress string, blockNumber int64) (bool, error) { + return g.Fetcher.FetchBool("stopped", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetStringName(contractAbi, contractAddress string, blockNumber int64) (string, error) { + return g.Fetcher.FetchString("name", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetHashName(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) { + return g.Fetcher.FetchHash("name", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetStringSymbol(contractAbi, contractAddress string, blockNumber int64) (string, error) { + return g.Fetcher.FetchString("symbol", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetHashSymbol(contractAbi, contractAddress string, blockNumber int64) (common.Hash, error) { + return g.Fetcher.FetchHash("symbol", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetDecimals(contractAbi, contractAddress string, blockNumber int64) (big.Int, error) { + return g.Fetcher.FetchBigInt("decimals", contractAbi, contractAddress, blockNumber, nil) +} + +func (g *Getter) GetBlockChain() core.BlockChain { + return g.Fetcher.BlockChain } type ERC20TokenRepository struct { diff --git a/pkg/fakes/mock_blockchain.go b/pkg/fakes/mock_blockchain.go index b4538c57..6dac17d4 100644 --- a/pkg/fakes/mock_blockchain.go +++ b/pkg/fakes/mock_blockchain.go @@ -13,7 +13,7 @@ type MockBlockChain struct { fetchContractDataPassedAbi string fetchContractDataPassedAddress string fetchContractDataPassedMethod string - fetchContractDataPassedMethodArgs []interface{} + fetchContractDataPassedMethodArgs []interface{} fetchContractDataPassedResult interface{} fetchContractDataPassedBlockNumber int64 getBlockByNumberErr error