feat(wallet) api to retrieve last activity timestamp
Also fix the lookup source for `GetRecipients` API Updates status-desktop #11169
This commit is contained in:
parent
d3e650d5e5
commit
ea7a389075
|
@ -364,7 +364,7 @@ const (
|
|||
)
|
||||
OR (filterActivityTypeReceive
|
||||
AND (filterAllAddresses
|
||||
OR (HEX(transfers.tx_to_address) IN filter_addresses))
|
||||
OR (HEX(transfers.tx_to_address) IN filter_addresses))
|
||||
)
|
||||
)
|
||||
AND (filterAllAddresses
|
||||
|
|
|
@ -3,6 +3,7 @@ package activity
|
|||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
eth "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
@ -91,28 +92,28 @@ type Filter struct {
|
|||
// TODO: consider sorting by saved address and contacts to offload the client from doing it at runtime
|
||||
func GetRecipients(ctx context.Context, db *sql.DB, offset int, limit int) (addresses []eth.Address, hasMore bool, err error) {
|
||||
rows, err := db.QueryContext(ctx, `
|
||||
SELECT
|
||||
transfers.address as to_address,
|
||||
transfers.timestamp AS timestamp
|
||||
FROM transfers
|
||||
WHERE transfers.multi_transaction_id = 0
|
||||
SELECT
|
||||
transfers.tx_to_address as to_address,
|
||||
transfers.timestamp AS timestamp
|
||||
FROM transfers
|
||||
WHERE transfers.multi_transaction_id = 0
|
||||
|
||||
UNION ALL
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
pending_transactions.to_address AS to_address,
|
||||
pending_transactions.timestamp AS timestamp
|
||||
FROM pending_transactions
|
||||
WHERE pending_transactions.multi_transaction_id = 0
|
||||
SELECT
|
||||
pending_transactions.to_address AS to_address,
|
||||
pending_transactions.timestamp AS timestamp
|
||||
FROM pending_transactions
|
||||
WHERE pending_transactions.multi_transaction_id = 0
|
||||
|
||||
UNION ALL
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
multi_transactions.to_address AS to_address,
|
||||
multi_transactions.timestamp AS timestamp
|
||||
FROM multi_transactions
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT ? OFFSET ?`, limit, offset)
|
||||
SELECT
|
||||
multi_transactions.to_address AS to_address,
|
||||
multi_transactions.timestamp AS timestamp
|
||||
FROM multi_transactions
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT ? OFFSET ?`, limit, offset)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
@ -137,3 +138,60 @@ func GetRecipients(ctx context.Context, db *sql.DB, offset int, limit int) (addr
|
|||
|
||||
return entries, hasMore, nil
|
||||
}
|
||||
|
||||
func GetOldestTimestamp(ctx context.Context, db *sql.DB, addresses []eth.Address) (timestamp int64, err error) {
|
||||
queryFormatString := `
|
||||
WITH filter_conditions AS (SELECT ? AS filterAllAddresses),
|
||||
filter_addresses(address) AS (
|
||||
SELECT * FROM (VALUES %s) WHERE (SELECT filterAllAddresses FROM filter_conditions) = 0
|
||||
)
|
||||
|
||||
SELECT
|
||||
transfers.tx_from_address AS from_address,
|
||||
transfers.tx_to_address AS to_address,
|
||||
transfers.timestamp AS timestamp
|
||||
FROM transfers, filter_conditions
|
||||
WHERE transfers.multi_transaction_id = 0
|
||||
AND (filterAllAddresses OR HEX(from_address) IN filter_addresses OR HEX(to_address) IN filter_addresses)
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
pending_transactions.from_address AS from_address,
|
||||
pending_transactions.to_address AS to_address,
|
||||
pending_transactions.timestamp AS timestamp
|
||||
FROM pending_transactions, filter_conditions
|
||||
WHERE pending_transactions.multi_transaction_id = 0
|
||||
AND (filterAllAddresses OR HEX(from_address) IN filter_addresses OR HEX(to_address) IN filter_addresses)
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
multi_transactions.from_address AS from_address,
|
||||
multi_transactions.to_address AS to_address,
|
||||
multi_transactions.timestamp AS timestamp
|
||||
FROM multi_transactions, filter_conditions
|
||||
WHERE filterAllAddresses OR HEX(from_address) IN filter_addresses OR HEX(to_address) IN filter_addresses
|
||||
ORDER BY timestamp ASC
|
||||
LIMIT 1`
|
||||
|
||||
filterAllAddresses := len(addresses) == 0
|
||||
involvedAddresses := noEntriesInTmpTableSQLValues
|
||||
if !filterAllAddresses {
|
||||
involvedAddresses = joinAddresses(addresses)
|
||||
}
|
||||
queryString := fmt.Sprintf(queryFormatString, involvedAddresses)
|
||||
|
||||
row := db.QueryRowContext(ctx, queryString, filterAllAddresses)
|
||||
var fromAddress, toAddress sql.NullString
|
||||
err = row.Scan(&fromAddress, &toAddress, ×tamp)
|
||||
if err == sql.ErrNoRows {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return timestamp, nil
|
||||
}
|
||||
|
|
|
@ -6,7 +6,10 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
eth "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
"github.com/status-im/status-go/appdatabase"
|
||||
"github.com/status-im/status-go/services/wallet/testutils"
|
||||
"github.com/status-im/status-go/services/wallet/transfer"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -61,3 +64,65 @@ func TestGetRecipients(t *testing.T) {
|
|||
require.Equal(t, 4, len(entries))
|
||||
require.True(t, hasMore)
|
||||
}
|
||||
|
||||
func TestGetOldestTimestampEmptyDB(t *testing.T) {
|
||||
db, close := setupTestFilterDB(t)
|
||||
defer close()
|
||||
|
||||
timestamp, err := GetOldestTimestamp(context.Background(), db, []eth.Address{eth.HexToAddress("0x1")})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), timestamp)
|
||||
}
|
||||
|
||||
func TestGetOldestTimestamp(t *testing.T) {
|
||||
db, close := setupTestFilterDB(t)
|
||||
defer close()
|
||||
|
||||
// Add 6 extractable transactions
|
||||
trs, _, _ := transfer.GenerateTestTransfers(t, db, 0, 7)
|
||||
for i := range trs {
|
||||
if i < 5 {
|
||||
transfer.InsertTestTransfer(t, db, trs[i].To, &trs[i])
|
||||
} else {
|
||||
transfer.InsertTestPendingTransaction(t, db, &trs[i])
|
||||
}
|
||||
}
|
||||
|
||||
multiTxs := []transfer.TestMultiTransaction{
|
||||
transfer.GenerateTestBridgeMultiTransaction(trs[0], trs[1]),
|
||||
transfer.GenerateTestSwapMultiTransaction(trs[2], testutils.SntSymbol, 100),
|
||||
}
|
||||
|
||||
// Extract oldest timestamp, no filter
|
||||
timestamp, err := GetOldestTimestamp(context.Background(), db, []eth.Address{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, multiTxs[0].Timestamp, timestamp)
|
||||
|
||||
// Test to filter
|
||||
timestamp, err = GetOldestTimestamp(context.Background(), db, []eth.Address{
|
||||
trs[3].To,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, trs[3].Timestamp, timestamp)
|
||||
|
||||
// Test from filter
|
||||
timestamp, err = GetOldestTimestamp(context.Background(), db, []eth.Address{
|
||||
trs[4].From,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, trs[4].Timestamp, timestamp)
|
||||
|
||||
// Test MT
|
||||
timestamp, err = GetOldestTimestamp(context.Background(), db, []eth.Address{
|
||||
multiTxs[1].FromAddress, trs[4].To,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, multiTxs[1].Timestamp, timestamp)
|
||||
|
||||
// Test Pending
|
||||
timestamp, err = GetOldestTimestamp(context.Background(), db, []eth.Address{
|
||||
trs[6].To,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, trs[6].Timestamp, timestamp)
|
||||
}
|
||||
|
|
|
@ -551,3 +551,8 @@ func (api *API) GetAllRecipients(ctx context.Context, offset int, limit int) (re
|
|||
result.Addresses, result.HasMore, err = activity.GetRecipients(ctx, api.s.db, offset, limit)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (api *API) GetOldestActivityTimestamp(ctx context.Context, addresses []common.Address) (timestamp int64, err error) {
|
||||
log.Debug("wallet.api.GetOldestActivityTimestamp", "addresses.len", len(addresses))
|
||||
return activity.GetOldestTimestamp(ctx, api.s.db, addresses)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue