diff --git a/services/wallet/downloader.go b/services/wallet/downloader.go index ad5eec420..f97c3ba94 100644 --- a/services/wallet/downloader.go +++ b/services/wallet/downloader.go @@ -101,36 +101,32 @@ func (d *ETHTransferDownloader) GetTransfersByNumber(ctx context.Context, number func (d *ETHTransferDownloader) getTransfersInBlock(ctx context.Context, blk *types.Block, accounts []common.Address) (rst []Transfer, err error) { for _, tx := range blk.Transactions() { - var address *common.Address - from, err := types.Sender(d.signer, tx) - if err != nil { - return nil, err - } - if any(from, accounts) { - address = &from - } else if tx.To() != nil && any(*tx.To(), accounts) { - address = tx.To() - } - if address != nil { - receipt, err := d.client.TransactionReceipt(ctx, tx.Hash()) + for _, address := range accounts { + from, err := types.Sender(d.signer, tx) if err != nil { return nil, err } - if isTokenTransfer(receipt.Logs) { - log.Debug("eth downloader found token transfer", "hash", tx.Hash()) - continue - } - rst = append(rst, Transfer{ - Type: ethTransfer, - ID: tx.Hash(), - Address: *address, - BlockNumber: blk.Number(), - BlockHash: blk.Hash(), - Timestamp: blk.Time(), - Transaction: tx, - From: from, - Receipt: receipt}) + if from == address || (tx.To() != nil && *tx.To() == address) { + receipt, err := d.client.TransactionReceipt(ctx, tx.Hash()) + if err != nil { + return nil, err + } + if isTokenTransfer(receipt.Logs) { + log.Debug("eth downloader found token transfer", "hash", tx.Hash()) + continue + } + rst = append(rst, Transfer{ + Type: ethTransfer, + ID: tx.Hash(), + Address: address, + BlockNumber: blk.Number(), + BlockHash: blk.Hash(), + Timestamp: blk.Time(), + Transaction: tx, + From: from, + Receipt: receipt}) + } } } // TODO(dshulyak) test that balance difference was covered by transactions @@ -311,15 +307,6 @@ func (d *ERC20TransfersDownloader) GetTransfersInRange(parent context.Context, f return transfers, nil } -func any(address common.Address, compare []common.Address) bool { - for _, c := range compare { - if c == address { - return true - } - } - return false -} - func isTokenTransfer(logs []*types.Log) bool { signature := crypto.Keccak256Hash([]byte(erc20TransferEventSignature)) for _, l := range logs { diff --git a/services/wallet/downloader_test.go b/services/wallet/downloader_test.go index 71188ea16..a9036740c 100644 --- a/services/wallet/downloader_test.go +++ b/services/wallet/downloader_test.go @@ -24,10 +24,10 @@ func TestETHTransfers(t *testing.T) { type ETHTransferSuite struct { suite.Suite - ethclient *ethclient.Client - identity *ecdsa.PrivateKey - faucet *ecdsa.PrivateKey - signer types.Signer + ethclient *ethclient.Client + identity, secondary *ecdsa.PrivateKey + faucet *ecdsa.PrivateKey + signer types.Signer downloader *ETHTransferDownloader } @@ -38,6 +38,8 @@ func (s *ETHTransferSuite) SetupTest() { s.Require().NoError(err) s.faucet, err = crypto.GenerateKey() s.Require().NoError(err) + s.secondary, err = crypto.GenerateKey() + s.Require().NoError(err) node, err := miner.NewDevNode(crypto.PubkeyToAddress(s.faucet.PublicKey)) s.Require().NoError(err) @@ -48,22 +50,33 @@ func (s *ETHTransferSuite) SetupTest() { s.ethclient = ethclient.NewClient(client) s.signer = types.NewEIP155Signer(big.NewInt(1337)) s.downloader = ÐTransferDownloader{ - signer: s.signer, - client: s.ethclient, - accounts: []common.Address{crypto.PubkeyToAddress(s.identity.PublicKey)}, + signer: s.signer, + client: s.ethclient, + accounts: []common.Address{ + crypto.PubkeyToAddress(s.identity.PublicKey), + crypto.PubkeyToAddress(s.secondary.PublicKey)}, } } +// signAndMineTx signs transaction with provided key and waits for it to be mined. +// uses configured faucet key if pkey is nil. +func (s *ETHTransferSuite) signAndMineTx(tx *types.Transaction, pkey *ecdsa.PrivateKey) { + if pkey == nil { + pkey = s.faucet + } + tx, err := types.SignTx(tx, s.signer, pkey) + s.Require().NoError(err) + s.Require().NoError(s.ethclient.SendTransaction(context.Background(), tx)) + timeout, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + _, err = bind.WaitMined(timeout, s.ethclient, tx) + s.Require().NoError(err) +} + func (s *ETHTransferSuite) TestNoBalance() { ctx := context.TODO() tx := types.NewTransaction(0, common.Address{1}, big.NewInt(1e18), 1e6, big.NewInt(10), nil) - tx, err := types.SignTx(tx, s.signer, s.faucet) - s.Require().NoError(err) - s.Require().NoError(s.ethclient.SendTransaction(ctx, tx)) - timeout, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - _, err = bind.WaitMined(timeout, s.ethclient, tx) - s.Require().NoError(err) + s.signAndMineTx(tx, nil) header, err := s.ethclient.HeaderByNumber(ctx, nil) s.Require().NoError(err) @@ -119,6 +132,20 @@ func (s *ETHTransferSuite) TestBalanceUpdatedOnOutbound() { s.Require().Len(transfers, 1) } +func (s *ETHTransferSuite) TestMultipleReferences() { + tx := types.NewTransaction(0, crypto.PubkeyToAddress(s.identity.PublicKey), big.NewInt(1e18), 1e6, big.NewInt(10), nil) + s.signAndMineTx(tx, nil) + tx = types.NewTransaction(0, crypto.PubkeyToAddress(s.secondary.PublicKey), big.NewInt(1e17), 1e6, big.NewInt(10), nil) + s.signAndMineTx(tx, s.identity) + + header, err := s.ethclient.HeaderByNumber(context.Background(), nil) + s.Require().NoError(err) + s.Require().Equal(big.NewInt(2), header.Number) + transfers, err := s.downloader.GetTransfers(context.Background(), toDBHeader(header)) + s.Require().NoError(err) + s.Require().Len(transfers, 2) +} + func TestERC20Transfers(t *testing.T) { suite.Run(t, new(ERC20TransferSuite)) }