fix(wallet): balance history used a wrong db for accessing accounts.

Balance history was not checked for all chains if no history on
some chain.
Removed `SetInitialRange` from wallet API as internal implementation.
This method was called on adding a brand new Status account to initialize
blocks_range table to avoid transfers history checks.
This commit is contained in:
Ivan Belyakov 2023-08-25 14:22:50 +02:00 committed by IvanBelyakoff
parent fbcda780ec
commit c24c3966e2
8 changed files with 38 additions and 106 deletions

View File

@ -132,30 +132,6 @@ Returns avaiable transfers in a given range.
]
```
### wallet_setInitialBlocksRange
Sets `zero block - latest block` range as scanned for an account. It is used when a new multiaccount is generated to avoid scanning transfers history.
#### Example
```json
{"jsonrpc":"2.0","id":7,"method":"wallet_setInitialBlocksRange","params":[]}
```
### setInitialBlocksRangeForChainIDs
Sets `zero block - latest block` range as scanned for an account. It is used when a new multiaccount is generated to avoid scanning transfers history.
#### Parameters
- `chainIDs`: `[]INT` - array of ethereum chain ID to be initialized
#### Example
```json
{"jsonrpc":"2.0","id":7,"method":"wallet_setInitialBlocksRangeForChainIDs","params":[[1, 2]]}
```
### wallet_watchTransaction
Starts watching for transaction confirmation/rejection. If transaction was not confirmed/rejected in 10 minutes the call is timed out with error.
@ -616,7 +592,7 @@ Emitted when history scanning is started.
Emitted when history scanning is ended.
4. `fetching-history-error`
4. `fetching-history-error`
Emitted when when history can't be fetched because some error. Error's decritption can be found in `message` field.
@ -630,12 +606,11 @@ Emitted when the application is connected to a non-archival node.
When a new multiaccount is created corresponding address will not contain any transaction. Thus no point in checking history, it will be empty.
1. Call `wallet_setInitialRange`
2. Call `wallet_checkRecentHistory`
3. On `recent-history-ready` request transactions via `wallet_getTransfersByAddress`
4. Repeat `wallet_checkRecentHistory` in N minutes (currently 20 minutes in `status-mobile` for upstream RPC node. If a custom node is used interval can be arbitrary)
1. Call `wallet_checkRecentHistory`
2. On `recent-history-ready` request transactions via `wallet_getTransfersByAddress`
3. Repeat `wallet_checkRecentHistory` in N minutes (currently 20 minutes in `status-mobile` for upstream RPC node. If a custom node is used interval can be arbitrary)
### Logging into application
### Logging into application
1. Call `wallet_checkRecentHistory`
2. On `recent-history-ready` request transactions via `wallet_getTransfersByAddress`
3. Repeat `wallet_checkRecentHistory` in N minutes (currently 20 minutes in `status-mobile` for upstream RPC node. If a custom node is used interval can be arbitrary)

View File

@ -66,15 +66,6 @@ type DerivedAddress struct {
AlreadyCreated bool `json:"alreadyCreated"`
}
// SetInitialBlocksRange sets initial blocks range
func (api *API) SetInitialBlocksRange(ctx context.Context) error {
return api.s.transferController.SetInitialBlocksRange([]uint64{api.s.rpcClient.UpstreamChainID})
}
func (api *API) SetInitialBlocksRangeForChainIDs(ctx context.Context, chainIDs []uint64) error {
return api.s.transferController.SetInitialBlocksRange(chainIDs)
}
func (api *API) CheckRecentHistory(ctx context.Context, addresses []common.Address) error {
return api.s.transferController.CheckRecentHistory([]uint64{api.s.rpcClient.UpstreamChainID}, addresses)
}

View File

@ -40,6 +40,7 @@ const (
type Service struct {
balance *Balance
db *sql.DB
accountsDB *accounts.Database
eventFeed *event.Feed
rpcClient *statusrpc.Client
networkManager *network.Manager
@ -56,10 +57,11 @@ type Service struct {
type chainIdentity uint64
func NewService(db *sql.DB, eventFeed *event.Feed, rpcClient *statusrpc.Client, tokenManager *token.Manager, marketManager *market.Manager) *Service {
func NewService(db *sql.DB, accountsDB *accounts.Database, eventFeed *event.Feed, rpcClient *statusrpc.Client, tokenManager *token.Manager, marketManager *market.Manager) *Service {
return &Service{
balance: NewBalance(NewBalanceDB(db)),
db: db,
accountsDB: accountsDB,
eventFeed: eventFeed,
rpcClient: rpcClient,
networkManager: rpcClient.NetworkManager,
@ -222,8 +224,6 @@ func (s *Service) GetBalanceHistory(ctx context.Context, chainIDs []uint64, addr
}
if len(data) > 0 {
allData[chainIdentity(chainID)] = data
} else {
return make([]*ValuePoint, 0), nil
}
}
@ -476,17 +476,13 @@ func sortTimeAsc(data map[chainIdentity][]*DataPoint, pos map[chainIdentity]int)
//
// expects ctx to have cancellation support and processing to be cancelled by the caller
func (s *Service) updateBalanceHistory(ctx context.Context) error {
accountsDB, err := accounts.NewDB(s.db)
addresses, err := s.accountsDB.GetWalletAddresses()
if err != nil {
return err
}
addresses, err := accountsDB.GetWalletAddresses()
if err != nil {
return err
}
areTestNetworksEnabled, err := accountsDB.GetTestNetworksEnabled()
areTestNetworksEnabled, err := s.accountsDB.GetTestNetworksEnabled()
if err != nil {
return err
}

View File

@ -43,7 +43,7 @@ func setupDummyServiceNoDependencies(t *testing.T) (service *Service, closeFn fu
rpcClient, err := statusRPC.NewClient(client, 1, upstreamConfig, nil, db)
require.NoError(t, err)
return NewService(db, nil, rpcClient, nil, market.NewManager(cryptoCompare, cryptoCompare, &event.Feed{})), func() {
return NewService(db, nil, nil, rpcClient, nil, market.NewManager(cryptoCompare, cryptoCompare, &event.Feed{})), func() {
require.NoError(t, db.Close())
}
}

View File

@ -100,7 +100,7 @@ func NewService(
coingecko := coingecko.NewClient()
marketManager := market.NewManager(cryptoCompare, coingecko, feed)
reader := NewReader(rpcClient, tokenManager, marketManager, accountsDB, NewPersistence(db), feed)
history := history.NewService(db, feed, rpcClient, tokenManager, marketManager)
history := history.NewService(db, accountsDB, feed, rpcClient, tokenManager, marketManager)
currency := currency.NewService(db, feed, tokenManager, marketManager)
activity := activity.NewService(db, tokenManager, feed, accountsDB)

View File

@ -6,7 +6,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/status-im/status-go/multiaccounts/accounts"
"github.com/status-im/status-go/services/wallet/bigint"
)
@ -60,23 +59,6 @@ func (b *BlockDAO) mergeBlocksRanges(chainIDs []uint64, accounts []common.Addres
return nil
}
func (b *BlockDAO) setInitialBlocksRange(chainID uint64, from *big.Int, to *big.Int) error {
accountsDB, err := accounts.NewDB(b.db)
if err != nil {
return err
}
watchAddress, err := accountsDB.GetWalletAddress()
if err != nil {
return err
}
err = b.insertRange(chainID, common.Address(watchAddress), from, to, big.NewInt(0), 0)
if err != nil {
return err
}
return nil
}
func (b *BlockDAO) mergeRanges(chainID uint64, account common.Address) (err error) {
var (
tx *sql.Tx

View File

@ -5,7 +5,6 @@ import (
"database/sql"
"fmt"
"math/big"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
@ -66,32 +65,6 @@ func (c *Controller) Stop() {
}
}
func (c *Controller) SetInitialBlocksRange(chainIDs []uint64) error {
chainClients, err := c.rpcClient.EthClients(chainIDs)
if err != nil {
return err
}
for chainID, chainClient := range chainClients {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
toHeader, err := chainClient.HeaderByNumber(ctx, nil)
if err != nil {
return err
}
from := big.NewInt(0)
err = c.blockDAO.setInitialBlocksRange(chainID, from, toHeader.Number)
if err != nil {
return err
}
}
return nil
}
func (c *Controller) CheckRecentHistory(chainIDs []uint64, accounts []common.Address) error {
if len(accounts) == 0 {
log.Info("no accounts provided")

View File

@ -57,6 +57,30 @@ type HistoryFetcher interface {
limit int64, fetchMore bool) ([]Transfer, error)
}
func NewOnDemandFetchStrategy(
db *Database,
blockDAO *BlockDAO,
feed *event.Feed,
transactionManager *TransactionManager,
pendingTxManager *transactions.PendingTxTracker,
tokenManager *token.Manager,
chainClients map[uint64]*chain.ClientWithFallback,
accounts []common.Address,
) *OnDemandFetchStrategy {
strategy := &OnDemandFetchStrategy{
db: db,
blockDAO: blockDAO,
feed: feed,
transactionManager: transactionManager,
pendingTxManager: pendingTxManager,
tokenManager: tokenManager,
chainClients: chainClients,
accounts: accounts,
}
return strategy
}
type OnDemandFetchStrategy struct {
db *Database
blockDAO *BlockDAO
@ -294,16 +318,7 @@ func (r *Reactor) createFetchStrategy(chainClients map[uint64]*chain.ClientWithF
)
}
return &OnDemandFetchStrategy{
db: r.db,
feed: r.feed,
blockDAO: r.blockDAO,
transactionManager: r.transactionManager,
pendingTxManager: r.pendingTxManager,
tokenManager: r.tokenManager,
chainClients: chainClients,
accounts: accounts,
}
return NewOnDemandFetchStrategy(r.db, r.blockDAO, r.feed, r.transactionManager, r.pendingTxManager, r.tokenManager, chainClients, accounts)
}
func (r *Reactor) getTransfersByAddress(ctx context.Context, chainID uint64, address common.Address, toBlock *big.Int,