[#4087] Omit history scanning on generated multiacc creation
This commit is contained in:
parent
74c13fd363
commit
42527723f2
|
@ -1329,6 +1329,7 @@ func (b *GethStatusBackend) generateOrImportAccount(mnemonic string, customizati
|
|||
// If restoring an account, we don't set the mnemonic
|
||||
if mnemonic == "" {
|
||||
settings.Mnemonic = &info.Mnemonic
|
||||
settings.OmitTransfersHistoryScan = true
|
||||
}
|
||||
|
||||
nodeConfig, err := defaultNodeConfig(settings.InstallationID, request)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
ALTER TABLE settings ADD COLUMN omit_transfers_history_scan BOOLEAN NOT NULL DEFAULT FALSE;
|
|
@ -447,6 +447,11 @@ var (
|
|||
protobufType: protobuf.SyncSetting_URL_UNFURLING_MODE,
|
||||
},
|
||||
}
|
||||
OmitTransfersHistoryScan = SettingField{
|
||||
reactFieldName: "omit-transfers-history-scan",
|
||||
dBColumnName: "omit_transfers_history_scan",
|
||||
valueHandler: BoolHandler,
|
||||
}
|
||||
|
||||
SettingFieldRegister = []SettingField{
|
||||
AnonMetricsShouldSend,
|
||||
|
|
|
@ -122,10 +122,11 @@ INSERT INTO settings (
|
|||
current_user_status,
|
||||
profile_pictures_show_to,
|
||||
profile_pictures_visibility,
|
||||
url_unfurling_mode
|
||||
url_unfurling_mode,
|
||||
omit_transfers_history_scan
|
||||
) VALUES (
|
||||
?,?,?,?,?,?,?,?,?,?,?,?,?,
|
||||
?,?,?,?,?,?,?,?,?,'id',?,?,?,?)`,
|
||||
?,?,?,?,?,?,?,?,?,'id',?,?,?,?,?)`,
|
||||
s.Address,
|
||||
s.Currency,
|
||||
s.CurrentNetwork,
|
||||
|
@ -152,6 +153,7 @@ INSERT INTO settings (
|
|||
s.ProfilePicturesShowTo,
|
||||
s.ProfilePicturesVisibility,
|
||||
s.URLUnfurlingMode,
|
||||
s.OmitTransfersHistoryScan,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -336,7 +338,8 @@ func (db *Database) GetSettings() (Settings, error) {
|
|||
profile_pictures_show_to, profile_pictures_visibility, wallet_root_address, wallet_set_up_passed, wallet_visible_tokens,
|
||||
waku_bloom_filter_mode, webview_allow_permission_requests, current_user_status, send_status_updates, gif_recents,
|
||||
gif_favorites, opensea_enabled, last_backup, backup_enabled, telemetry_server_url, auto_message_enabled, gif_api_key,
|
||||
test_networks_enabled, mutual_contact_enabled, profile_migration_needed, is_sepolia_enabled, url_unfurling_mode
|
||||
test_networks_enabled, mutual_contact_enabled, profile_migration_needed, is_sepolia_enabled, url_unfurling_mode,
|
||||
omit_transfers_history_scan
|
||||
FROM
|
||||
settings
|
||||
WHERE
|
||||
|
@ -412,6 +415,7 @@ func (db *Database) GetSettings() (Settings, error) {
|
|||
&s.ProfileMigrationNeeded,
|
||||
&s.IsSepoliaEnabled,
|
||||
&s.URLUnfurlingMode,
|
||||
&s.OmitTransfersHistoryScan,
|
||||
)
|
||||
|
||||
return s, err
|
||||
|
|
|
@ -143,6 +143,7 @@ type Settings struct {
|
|||
MessagesFromContactsOnly bool `json:"messages-from-contacts-only"`
|
||||
Mnemonic *string `json:"mnemonic,omitempty"`
|
||||
MnemonicRemoved bool `json:"mnemonic-removed?,omitempty"`
|
||||
OmitTransfersHistoryScan bool `json:"omit-transfers-history-scan?,omitempty"`
|
||||
MutualContactEnabled bool `json:"mutual-contact-enabled?"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Networks *json.RawMessage `json:"networks/networks"`
|
||||
|
|
|
@ -141,6 +141,7 @@ func (api *API) GetTokensBalances(ctx context.Context, accounts, addresses []com
|
|||
|
||||
// @deprecated
|
||||
func (api *API) GetTokensBalancesForChainIDs(ctx context.Context, chainIDs []uint64, accounts, addresses []common.Address) (map[common.Address]map[common.Address]*hexutil.Big, error) {
|
||||
log.Debug("wallet.api.GetTokensBalances", "accounts", accounts, "addresses", addresses)
|
||||
clients, err := api.s.rpcClient.EthClients(chainIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -97,7 +97,7 @@ func NewService(
|
|||
tokenManager := token.NewTokenManager(db, rpcClient, rpcClient.NetworkManager)
|
||||
savedAddressesManager := &SavedAddressesManager{db: db}
|
||||
transactionManager := transfer.NewTransactionManager(db, gethManager, transactor, config, accountsDB, pendingTxManager, feed)
|
||||
transferController := transfer.NewTransferController(db, rpcClient, accountFeed, feed, transactionManager, pendingTxManager,
|
||||
transferController := transfer.NewTransferController(db, accountsDB, rpcClient, accountFeed, feed, transactionManager, pendingTxManager,
|
||||
tokenManager, balanceCacher, config.WalletConfig.LoadAllTransfers)
|
||||
cryptoCompare := cryptocompare.NewClient()
|
||||
coingecko := coingecko.NewClient()
|
||||
|
|
|
@ -509,7 +509,7 @@ func loadTransfersLoop(ctx context.Context, account common.Address, blockDAO *Bl
|
|||
func newLoadBlocksAndTransfersCommand(account common.Address, db *Database,
|
||||
blockDAO *BlockDAO, chainClient chain.ClientInterface, feed *event.Feed,
|
||||
transactionManager *TransactionManager, pendingTxManager *transactions.PendingTxTracker,
|
||||
tokenManager *token.Manager, balanceCacher balance.Cacher) *loadBlocksAndTransfersCommand {
|
||||
tokenManager *token.Manager, balanceCacher balance.Cacher, omitHistory bool) *loadBlocksAndTransfersCommand {
|
||||
|
||||
return &loadBlocksAndTransfersCommand{
|
||||
account: account,
|
||||
|
@ -524,6 +524,7 @@ func newLoadBlocksAndTransfersCommand(account common.Address, db *Database,
|
|||
pendingTxManager: pendingTxManager,
|
||||
tokenManager: tokenManager,
|
||||
blocksLoadedCh: make(chan []*DBHeader, 100),
|
||||
omitHistory: omitHistory,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,6 +542,7 @@ type loadBlocksAndTransfersCommand struct {
|
|||
pendingTxManager *transactions.PendingTxTracker
|
||||
tokenManager *token.Manager
|
||||
blocksLoadedCh chan []*DBHeader
|
||||
omitHistory bool
|
||||
|
||||
// Not to be set by the caller
|
||||
transfersLoaded bool // For event RecentHistoryReady to be sent only once per account during app lifetime
|
||||
|
@ -591,7 +593,7 @@ func (c *loadBlocksAndTransfersCommand) startTransfersLoop(ctx context.Context)
|
|||
|
||||
func (c *loadBlocksAndTransfersCommand) fetchHistoryBlocks(ctx context.Context, group *async.Group, blocksLoadedCh chan []*DBHeader) error {
|
||||
|
||||
log.Debug("fetchHistoryBlocks start", "chainID", c.chainClient.NetworkID(), "account", c.account)
|
||||
log.Debug("fetchHistoryBlocks start", "chainID", c.chainClient.NetworkID(), "account", c.account, "omit", c.omitHistory)
|
||||
|
||||
headNum, err := getHeadBlockNumber(ctx, c.chainClient)
|
||||
if err != nil {
|
||||
|
@ -599,6 +601,13 @@ func (c *loadBlocksAndTransfersCommand) fetchHistoryBlocks(ctx context.Context,
|
|||
return err // Might need to retry a couple of times
|
||||
}
|
||||
|
||||
if c.omitHistory {
|
||||
blockRange := &BlockRange{nil, big.NewInt(0), headNum}
|
||||
err := c.blockRangeDAO.upsertRange(c.chainClient.NetworkID(), c.account, blockRange)
|
||||
log.Debug("fetchHistoryBlocks omit history", "chainID", c.chainClient.NetworkID(), "account", c.account, "headNum", headNum, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
blockRange, err := loadBlockRangeInfo(c.chainClient.NetworkID(), c.account, c.blockRangeDAO)
|
||||
if err != nil {
|
||||
log.Error("findBlocksCommand loadBlockRangeInfo", "error", err)
|
||||
|
|
|
@ -2,6 +2,7 @@ package transfer
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -9,6 +10,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
|
@ -28,7 +30,9 @@ import (
|
|||
"github.com/status-im/status-go/params"
|
||||
statusRpc "github.com/status-im/status-go/rpc"
|
||||
"github.com/status-im/status-go/rpc/network"
|
||||
walletcommon "github.com/status-im/status-go/services/wallet/common"
|
||||
"github.com/status-im/status-go/services/wallet/token"
|
||||
"github.com/status-im/status-go/transactions"
|
||||
"github.com/status-im/status-go/walletdatabase"
|
||||
)
|
||||
|
||||
|
@ -45,6 +49,7 @@ type TestClient struct {
|
|||
printPreparedData bool
|
||||
rw sync.RWMutex
|
||||
callsCounter map[string]int
|
||||
currentBlock uint64
|
||||
}
|
||||
|
||||
func (tc *TestClient) incCounter(method string) {
|
||||
|
@ -165,6 +170,10 @@ func (tc *TestClient) tokenBalanceAt(token common.Address, blockNumber *big.Int)
|
|||
|
||||
func (tc *TestClient) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
|
||||
tc.incCounter("HeaderByNumber")
|
||||
if number == nil {
|
||||
number = big.NewInt(int64(tc.currentBlock))
|
||||
}
|
||||
|
||||
if tc.traceAPICalls {
|
||||
tc.t.Log("HeaderByNumber", number)
|
||||
}
|
||||
|
@ -804,3 +813,106 @@ func TestFindBlocksCommand(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
type MockETHClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *MockETHClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error {
|
||||
args := m.Called(ctx, b)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
type MockChainClient struct {
|
||||
mock.Mock
|
||||
|
||||
clients map[walletcommon.ChainID]*MockETHClient
|
||||
}
|
||||
|
||||
func newMockChainClient() *MockChainClient {
|
||||
return &MockChainClient{
|
||||
clients: make(map[walletcommon.ChainID]*MockETHClient),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MockChainClient) AbstractEthClient(chainID walletcommon.ChainID) (chain.BatchCallClient, error) {
|
||||
if _, ok := m.clients[chainID]; !ok {
|
||||
panic(fmt.Sprintf("no mock client for chainID %d", chainID))
|
||||
}
|
||||
return m.clients[chainID], nil
|
||||
}
|
||||
|
||||
func TestFetchTransfersForLoadedBlocks(t *testing.T) {
|
||||
db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
|
||||
require.NoError(t, err)
|
||||
tm := &TransactionManager{db, nil, nil, nil, nil, nil, nil, nil, nil, nil}
|
||||
|
||||
wdb := NewDB(db)
|
||||
blockChannel := make(chan []*DBHeader, 100)
|
||||
|
||||
tc := &TestClient{
|
||||
t: t,
|
||||
balances: [][]int{},
|
||||
outgoingERC20Transfers: []testERC20Transfer{},
|
||||
incomingERC20Transfers: []testERC20Transfer{},
|
||||
callsCounter: map[string]int{},
|
||||
currentBlock: 100,
|
||||
}
|
||||
|
||||
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
|
||||
client.SetClient(tc.NetworkID(), tc)
|
||||
tokenManager := token.NewTokenManager(db, client, network.NewManager(db))
|
||||
|
||||
tokenManager.SetTokens([]*token.Token{
|
||||
{
|
||||
Address: tokenTXXAddress,
|
||||
Symbol: "TXX",
|
||||
Decimals: 18,
|
||||
ChainID: tc.NetworkID(),
|
||||
Name: "Test Token 1",
|
||||
Verified: true,
|
||||
},
|
||||
{
|
||||
Address: tokenTXYAddress,
|
||||
Symbol: "TXY",
|
||||
Decimals: 18,
|
||||
ChainID: tc.NetworkID(),
|
||||
Name: "Test Token 2",
|
||||
Verified: true,
|
||||
},
|
||||
})
|
||||
|
||||
chainClient := newMockChainClient()
|
||||
tracker := transactions.NewPendingTxTracker(db, chainClient, nil, &event.Feed{}, transactions.PendingCheckInterval)
|
||||
cmd := &loadBlocksAndTransfersCommand{
|
||||
account: common.HexToAddress("0x1234"),
|
||||
db: wdb,
|
||||
blockRangeDAO: &BlockRangeSequentialDAO{wdb.client},
|
||||
blockDAO: &BlockDAO{db},
|
||||
chainClient: tc,
|
||||
feed: &event.Feed{},
|
||||
balanceCacher: balance.NewCacherWithTTL(5 * time.Minute),
|
||||
errorsCount: 0,
|
||||
transactionManager: tm,
|
||||
pendingTxManager: tracker,
|
||||
tokenManager: tokenManager,
|
||||
blocksLoadedCh: blockChannel,
|
||||
omitHistory: true,
|
||||
}
|
||||
|
||||
tc.prepareBalanceHistory(int(tc.currentBlock))
|
||||
tc.prepareTokenBalanceHistory(int(tc.currentBlock))
|
||||
tc.traceAPICalls = true
|
||||
|
||||
ctx := context.Background()
|
||||
group := async.NewGroup(ctx)
|
||||
err = cmd.fetchHistoryBlocks(ctx, group, blockChannel)
|
||||
require.NoError(t, err)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Log("ERROR")
|
||||
case <-group.WaitAsync():
|
||||
require.Equal(t, 1, tc.getCounter())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
statusaccounts "github.com/status-im/status-go/multiaccounts/accounts"
|
||||
"github.com/status-im/status-go/multiaccounts/settings"
|
||||
"github.com/status-im/status-go/rpc"
|
||||
"github.com/status-im/status-go/rpc/chain"
|
||||
"github.com/status-im/status-go/services/accounts/accountsevent"
|
||||
|
@ -21,6 +23,7 @@ import (
|
|||
|
||||
type Controller struct {
|
||||
db *Database
|
||||
accountsDB *statusaccounts.Database
|
||||
rpcClient *rpc.Client
|
||||
blockDAO *BlockDAO
|
||||
reactor *Reactor
|
||||
|
@ -34,13 +37,14 @@ type Controller struct {
|
|||
loadAllTransfers bool
|
||||
}
|
||||
|
||||
func NewTransferController(db *sql.DB, rpcClient *rpc.Client, accountFeed *event.Feed, transferFeed *event.Feed,
|
||||
func NewTransferController(db *sql.DB, accountsDB *statusaccounts.Database, rpcClient *rpc.Client, accountFeed *event.Feed, transferFeed *event.Feed,
|
||||
transactionManager *TransactionManager, pendingTxManager *transactions.PendingTxTracker, tokenManager *token.Manager,
|
||||
balanceCacher balance.Cacher, loadAllTransfers bool) *Controller {
|
||||
|
||||
blockDAO := &BlockDAO{db}
|
||||
return &Controller{
|
||||
db: NewDB(db),
|
||||
accountsDB: accountsDB,
|
||||
blockDAO: blockDAO,
|
||||
rpcClient: rpcClient,
|
||||
accountFeed: accountFeed,
|
||||
|
@ -71,12 +75,10 @@ func (c *Controller) Stop() {
|
|||
|
||||
func (c *Controller) CheckRecentHistory(chainIDs []uint64, accounts []common.Address) error {
|
||||
if len(accounts) == 0 {
|
||||
log.Info("no accounts provided")
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(chainIDs) == 0 {
|
||||
log.Info("no chain provided")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -96,8 +98,21 @@ func (c *Controller) CheckRecentHistory(chainIDs []uint64, accounts []common.Add
|
|||
return err
|
||||
}
|
||||
} else {
|
||||
multiaccSettings, err := c.accountsDB.GetSettings()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
omitHistory := multiaccSettings.OmitTransfersHistoryScan
|
||||
if omitHistory {
|
||||
err := c.accountsDB.SaveSettingField(settings.OmitTransfersHistoryScan, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
c.reactor = NewReactor(c.db, c.blockDAO, c.TransferFeed, c.transactionManager,
|
||||
c.pendingTxManager, c.tokenManager, c.balanceCacher)
|
||||
c.pendingTxManager, c.tokenManager, c.balanceCacher, omitHistory)
|
||||
|
||||
err = c.reactor.start(chainClients, accounts, c.loadAllTransfers)
|
||||
if err != nil {
|
||||
|
|
|
@ -259,11 +259,12 @@ type Reactor struct {
|
|||
tokenManager *token.Manager
|
||||
strategy HistoryFetcher
|
||||
balanceCacher balance.Cacher
|
||||
omitHistory bool
|
||||
}
|
||||
|
||||
func NewReactor(db *Database, blockDAO *BlockDAO, feed *event.Feed, tm *TransactionManager,
|
||||
pendingTxManager *transactions.PendingTxTracker, tokenManager *token.Manager,
|
||||
balanceCacher balance.Cacher) *Reactor {
|
||||
balanceCacher balance.Cacher, omitHistory bool) *Reactor {
|
||||
return &Reactor{
|
||||
db: db,
|
||||
blockDAO: blockDAO,
|
||||
|
@ -272,6 +273,7 @@ func NewReactor(db *Database, blockDAO *BlockDAO, feed *event.Feed, tm *Transact
|
|||
pendingTxManager: pendingTxManager,
|
||||
tokenManager: tokenManager,
|
||||
balanceCacher: balanceCacher,
|
||||
omitHistory: omitHistory,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,6 +313,7 @@ func (r *Reactor) createFetchStrategy(chainClients map[uint64]chain.ClientInterf
|
|||
chainClients,
|
||||
accounts,
|
||||
r.balanceCacher,
|
||||
r.omitHistory,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ func NewSequentialFetchStrategy(db *Database, blockDAO *BlockDAO, feed *event.Fe
|
|||
chainClients map[uint64]chain.ClientInterface,
|
||||
accounts []common.Address,
|
||||
balanceCacher balance.Cacher,
|
||||
omitHistory bool,
|
||||
) *SequentialFetchStrategy {
|
||||
|
||||
return &SequentialFetchStrategy{
|
||||
|
@ -34,6 +35,7 @@ func NewSequentialFetchStrategy(db *Database, blockDAO *BlockDAO, feed *event.Fe
|
|||
chainClients: chainClients,
|
||||
accounts: accounts,
|
||||
balanceCacher: balanceCacher,
|
||||
omitHistory: omitHistory,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,13 +51,14 @@ type SequentialFetchStrategy struct {
|
|||
chainClients map[uint64]chain.ClientInterface
|
||||
accounts []common.Address
|
||||
balanceCacher balance.Cacher
|
||||
omitHistory bool
|
||||
}
|
||||
|
||||
func (s *SequentialFetchStrategy) newCommand(chainClient chain.ClientInterface,
|
||||
account common.Address) async.Commander {
|
||||
|
||||
return newLoadBlocksAndTransfersCommand(account, s.db, s.blockDAO, chainClient, s.feed,
|
||||
s.transactionManager, s.pendingTxManager, s.tokenManager, s.balanceCacher)
|
||||
s.transactionManager, s.pendingTxManager, s.tokenManager, s.balanceCacher, s.omitHistory)
|
||||
}
|
||||
|
||||
func (s *SequentialFetchStrategy) start() error {
|
||||
|
|
Loading…
Reference in New Issue