fix(wallet): do not return gas-only ETH entries of transfers table for
activities request Closes #4618
This commit is contained in:
parent
dad2ec3f66
commit
7d1927396a
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
@ -208,7 +209,7 @@ SELECT
|
|||
WHEN transfers.tx_from_address = zeroAddress AND transfers.type = "erc20" THEN substr(json_extract(tx, '$.input'), 1, 10)
|
||||
ELSE NULL
|
||||
END AS method_hash,
|
||||
CASE
|
||||
CASE
|
||||
WHEN transfers.tx_from_address = zeroAddress AND transfers.type = "erc20" THEN (SELECT 1 FROM json_each(transfers.receipt, '$.logs' ) WHERE json_extract( value, '$.topics[0]' ) = communityMintEvent)
|
||||
ELSE NULL
|
||||
END AS community_mint_event
|
||||
|
@ -254,11 +255,11 @@ WHERE
|
|||
AND (
|
||||
transfers.type = 'erc721'
|
||||
OR (
|
||||
transfers.type = 'erc20'
|
||||
transfers.type = 'erc20'
|
||||
AND (
|
||||
(method_hash IS NOT NULL AND method_hash IN mint_methods)
|
||||
OR community_mint_event IS NOT NULL
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -281,11 +282,11 @@ WHERE
|
|||
AND (
|
||||
transfers.type = 'erc721'
|
||||
OR (
|
||||
transfers.type = 'erc20'
|
||||
transfers.type = 'erc20'
|
||||
AND (
|
||||
(method_hash IS NOT NULL AND method_hash IN mint_methods)
|
||||
OR community_mint_event IS NOT NULL
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -583,4 +584,4 @@ WHERE
|
|||
ORDER BY
|
||||
timestamp DESC
|
||||
LIMIT
|
||||
? OFFSET ?
|
||||
? OFFSET ?
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue