fix(wallet): do not return gas-only ETH entries of transfers table for

activities request

Closes #4618
This commit is contained in:
Ivan Belyakov 2024-01-24 14:00:08 +01:00 committed by IvanBelyakoff
parent dad2ec3f66
commit 7d1927396a
5 changed files with 119 additions and 20 deletions

View File

@ -1378,3 +1378,74 @@ func TestGetMultiTxDetails(t *testing.T) {
require.Equal(t, td.multiTx1Tr2.Hash, details.ChainDetails[1].Hash)
require.Equal(t, td.multiTx1Tr2.Contract, *details.ChainDetails[1].Contract)
}
func TestGetActivityEntriesSkipEthGasFeeOnlyTransfers(t *testing.T) {
deps, close := setupTestActivityDB(t)
defer close()
to := eth.Address{0x1}
from := eth.Address{0x2}
hash := eth.Hash{0x3}
blkNum := int64(1)
chainID := common.ChainID(1)
nonce := uint64(1)
// Insert 0-value gas-only ETH transfer as a result of token transfer's gas fee
transfer.InsertTestTransfer(t, deps.db, to, &transfer.TestTransfer{
TestTransaction: transfer.TestTransaction{
ChainID: chainID,
From: from,
Hash: hash,
BlkNumber: blkNum,
Nonce: nonce,
},
To: to,
Value: 0,
})
entries, err := getActivityEntries(context.Background(), deps, []eth.Address{to}, true, []common.ChainID{chainID}, Filter{}, 0, 10)
require.NoError(t, err)
require.Equal(t, 1, len(entries))
require.Equal(t, hash, entries[0].transaction.Hash)
// Insert token transfer
transfer.InsertTestTransferWithOptions(t, deps.db, to,
&transfer.TestTransfer{
TestTransaction: transfer.TestTransaction{
ChainID: chainID,
From: from,
Hash: hash,
BlkNumber: blkNum,
Nonce: nonce,
},
To: to,
Value: 1,
},
&transfer.TestTransferOptions{
TokenAddress: eth.Address{0x4},
},
)
// Gas-fee-only transfer should be removed, so we get only 1 transfer again
entries, err = getActivityEntries(context.Background(), deps, []eth.Address{to}, true, []common.ChainID{chainID}, Filter{}, 0, 10)
require.NoError(t, err)
require.Equal(t, 1, len(entries))
require.Equal(t, contractTypeFromDBType("erc20"), entries[0].transferType)
// Insert real 0-value ETH transfer
transfer.InsertTestTransfer(t, deps.db, to, &transfer.TestTransfer{
TestTransaction: transfer.TestTransaction{
ChainID: chainID,
From: from,
Hash: eth.Hash{0x5}, // another hash
BlkNumber: blkNum,
Nonce: nonce + 1, // another nonce
},
To: to,
Value: 0, // 0-value as well
})
entries, err = getActivityEntries(context.Background(), deps, []eth.Address{to}, true, []common.ChainID{chainID}, Filter{}, 0, 10)
require.NoError(t, err)
require.Equal(t, 2, len(entries))
}

View File

@ -157,6 +157,7 @@ layer2_networks(network_id) AS (
mint_methods(method_hash) AS (
%s
)
SELECT
transfers.hash AS transfer_hash,
NULL AS pending_hash,

View File

@ -90,8 +90,8 @@ func (b *BlockRangeSequentialDAO) upsertRange(chainID uint64, account common.Add
return err
}
ethBlockRange := prepareUpdatedBlockRange(chainID, account, ethTokensBlockRange.eth, newBlockRange.eth)
tokensBlockRange := prepareUpdatedBlockRange(chainID, account, ethTokensBlockRange.tokens, newBlockRange.tokens)
ethBlockRange := prepareUpdatedBlockRange(ethTokensBlockRange.eth, newBlockRange.eth)
tokensBlockRange := prepareUpdatedBlockRange(ethTokensBlockRange.tokens, newBlockRange.tokens)
log.Debug("update eth and tokens blocks range", "account", account, "chainID", chainID,
"eth.start", ethBlockRange.Start, "eth.first", ethBlockRange.FirstKnown, "eth.last", ethBlockRange.LastKnown,
@ -117,7 +117,7 @@ func (b *BlockRangeSequentialDAO) upsertEthRange(chainID uint64, account common.
return err
}
blockRange := prepareUpdatedBlockRange(chainID, account, ethTokensBlockRange.eth, newBlockRange)
blockRange := prepareUpdatedBlockRange(ethTokensBlockRange.eth, newBlockRange)
log.Debug("update eth blocks range", "account", account, "chainID", chainID,
"start", blockRange.Start, "first", blockRange.FirstKnown, "last", blockRange.LastKnown, "old hash", ethTokensBlockRange.balanceCheckHash)
@ -146,7 +146,7 @@ func (b *BlockRangeSequentialDAO) updateTokenRange(chainID uint64, account commo
return err
}
blockRange := prepareUpdatedBlockRange(chainID, account, ethTokensBlockRange.tokens, newBlockRange)
blockRange := prepareUpdatedBlockRange(ethTokensBlockRange.tokens, newBlockRange)
log.Debug("update tokens blocks range", "account", account, "chainID", chainID,
"start", blockRange.Start, "first", blockRange.FirstKnown, "last", blockRange.LastKnown, "old hash", ethTokensBlockRange.balanceCheckHash)
@ -162,7 +162,7 @@ func (b *BlockRangeSequentialDAO) updateTokenRange(chainID uint64, account commo
return err
}
func prepareUpdatedBlockRange(chainID uint64, account common.Address, blockRange, newBlockRange *BlockRange) *BlockRange {
func prepareUpdatedBlockRange(blockRange, newBlockRange *BlockRange) *BlockRange {
// Update existing range
if blockRange != nil {
if newBlockRange != nil {

View File

@ -296,7 +296,7 @@ func (c *transfersCommand) saveAndConfirmPending(allTransfers []Transfer, blockN
if resErr != nil {
return resErr
}
notifyFunctions := make([]func(), 0)
notifyFunctions := c.confirmPendingTransactions(tx, allTransfers)
defer func() {
if resErr == nil {
commitErr := tx.Commit()
@ -314,6 +314,17 @@ func (c *transfersCommand) saveAndConfirmPending(allTransfers []Transfer, blockN
}
}()
resErr = saveTransfersMarkBlocksLoaded(tx, c.chainClient.NetworkID(), c.address, allTransfers, []*big.Int{blockNum})
if resErr != nil {
log.Error("SaveTransfers error", "error", resErr)
}
return resErr
}
func (c *transfersCommand) confirmPendingTransactions(tx *sql.Tx, allTransfers []Transfer) (notifyFunctions []func()) {
notifyFunctions = make([]func(), 0)
// Confirm all pending transactions that are included in this block
for i, tr := range allTransfers {
chainID := w_common.ChainID(tr.NetworkID)
@ -351,13 +362,7 @@ func (c *transfersCommand) saveAndConfirmPending(allTransfers []Transfer, blockN
notifyFunctions = append(notifyFunctions, notify)
}
}
resErr = saveTransfersMarkBlocksLoaded(tx, c.chainClient.NetworkID(), c.address, allTransfers, []*big.Int{blockNum})
if resErr != nil {
log.Error("SaveTransfers error", "error", resErr)
}
return resErr
return notifyFunctions
}
// Mark all subTxs of a given Tx with the same multiTxID
@ -542,7 +547,7 @@ func (c *loadTransfersCommand) Command() async.Command {
}.Run
}
// This command always returs nil, even if there is an error in one of the commands.
// This command always returns nil, even if there is an error in one of the commands.
// `transferCommand`s retry until maxError, but this command doesn't retry.
// In case some transfer is not loaded after max retries, it will be retried only after restart of the app.
// Currently there is no implementation to keep retrying until success. I think this should be implemented

View File

@ -492,6 +492,28 @@ func updateOrInsertTransfersDBFields(creator statementCreator, transfers []trans
log.Error("can't save transfer", "b-hash", t.blockHash, "b-n", t.blockNumber, "a", t.address, "h", t.id)
return err
}
err = removeGasOnlyEthTransfer(creator, t)
if err != nil {
log.Error("can't remove gas only eth transfer", "b-hash", t.blockHash, "b-n", t.blockNumber, "a", t.address, "h", t.id, "err", err)
// no return err, since it's not critical
}
}
return nil
}
func removeGasOnlyEthTransfer(creator statementCreator, t transferDBFields) error {
if t.transferType != w_common.EthTransfer {
query, err := creator.Prepare(`DELETE FROM transfers WHERE tx_hash = ? AND address = ? AND network_id = ?
AND account_nonce = ? AND type = 'eth' AND amount_padded128hex = '00000000000000000000000000000000'`)
if err != nil {
return err
}
_, err = query.Exec(t.txHash, t.address, t.chainID, t.txNonce)
if err != nil {
return err
}
}
return nil
}