From 9a94a82fd629918d65b20ed8eb61b60681a0b08c Mon Sep 17 00:00:00 2001 From: Brian Sztamfater Date: Fri, 6 Dec 2024 09:48:12 -0300 Subject: [PATCH] fix!: add forceRefresh parameter to FetchOrGetCachedWalletBalances endpoint (#6160) Signed-off-by: Brian Sztamfater --- protocol/messenger_wallet.go | 2 +- services/wallet/api.go | 6 +-- services/wallet/api_test.go | 84 ++++++++++++++++++++++++++++++++++++ services/wallet/reader.go | 12 ++++++ 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/protocol/messenger_wallet.go b/protocol/messenger_wallet.go index 2c56dfb86..8245c36f2 100644 --- a/protocol/messenger_wallet.go +++ b/protocol/messenger_wallet.go @@ -50,7 +50,7 @@ func (m *Messenger) retrieveWalletBalances() error { defer cancel() // TODO: publish tokens as a signal - _, err = m.walletAPI.FetchOrGetCachedWalletBalances(ctx, ethAccounts) + _, err = m.walletAPI.FetchOrGetCachedWalletBalances(ctx, ethAccounts, false) if err != nil { return err } diff --git a/services/wallet/api.go b/services/wallet/api.go index 5abe83087..0ee72bd36 100644 --- a/services/wallet/api.go +++ b/services/wallet/api.go @@ -50,7 +50,7 @@ func NewAPI(s *Service) *API { // API is class with methods available over RPC. type API struct { s *Service - reader *Reader + reader ReaderInterface } func (api *API) StartWallet(ctx context.Context) error { @@ -84,7 +84,7 @@ func (api *API) GetBalancesByChain(ctx context.Context, chainIDs []uint64, addre return api.s.tokenManager.GetBalancesByChain(ctx, clients, addresses, tokens) } -func (api *API) FetchOrGetCachedWalletBalances(ctx context.Context, addresses []common.Address) (map[common.Address][]token.StorageToken, error) { +func (api *API) FetchOrGetCachedWalletBalances(ctx context.Context, addresses []common.Address, forceRefresh bool) (map[common.Address][]token.StorageToken, error) { activeNetworks, err := api.s.rpcClient.NetworkManager.GetActiveNetworks() if err != nil { return nil, err @@ -96,7 +96,7 @@ func (api *API) FetchOrGetCachedWalletBalances(ctx context.Context, addresses [] return nil, err } - return api.reader.FetchOrGetCachedWalletBalances(ctx, clients, addresses, false) + return api.reader.FetchOrGetCachedWalletBalances(ctx, clients, addresses, forceRefresh) } type DerivedAddress struct { diff --git a/services/wallet/api_test.go b/services/wallet/api_test.go index dd41ce9a5..204585df4 100644 --- a/services/wallet/api_test.go +++ b/services/wallet/api_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/event" "github.com/stretchr/testify/require" @@ -19,9 +20,11 @@ import ( "github.com/status-im/status-go/multiaccounts/accounts" "github.com/status-im/status-go/params" "github.com/status-im/status-go/rpc" + mock_reader "github.com/status-im/status-go/services/wallet/mock/reader" "github.com/status-im/status-go/services/wallet/onramp" mock_onramp "github.com/status-im/status-go/services/wallet/onramp/mock" "github.com/status-im/status-go/services/wallet/requests" + "github.com/status-im/status-go/services/wallet/token" "github.com/status-im/status-go/services/wallet/walletconnect" "github.com/status-im/status-go/t/helpers" "github.com/status-im/status-go/walletdatabase" @@ -201,3 +204,84 @@ func TestAPI_GetAddressDetails(t *testing.T) { require.NoError(t, err) require.Equal(t, true, details.HasActivity) } + +// TestAPI_FetchOrGetCachedWalletBalances +func TestAPI_FetchOrGetCachedWalletBalances(t *testing.T) { + appDB, err := helpers.SetupTestMemorySQLDB(appdatabase.DbInitializer{}) + require.NoError(t, err) + defer appDB.Close() + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + mockReader := mock_reader.NewMockReaderInterface(mockCtrl) + providerConfig := params.ProviderConfig{ + Enabled: true, + Name: rpc.ProviderStatusProxy, + User: "user1", + Password: "pass1", + } + providerConfigs := []params.ProviderConfig{providerConfig} + + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Fprintln(w, `{"result": "0x10"}`) + })) + defer server.Close() + + chainID := uint64(1) + + networks := []params.Network{ + { + ChainID: chainID, + DefaultRPCURL: server.URL + "/nodefleet/", + }, + } + config := rpc.ClientConfig{ + Client: nil, + UpstreamChainID: chainID, + Networks: networks, + DB: appDB, + WalletFeed: nil, + ProviderConfigs: providerConfigs, + } + c, err := rpc.NewClient(config) + require.NoError(t, err) + + testTokenAddress1 := common.Address{0x34} + testAccAddress1 := common.Address{0x12} + storageToken := token.StorageToken{ + Token: token.Token{ + Name: "USD Tether", + Symbol: "USDT", + Decimals: 18, + }, + BalancesPerChain: map[uint64]token.ChainBalance{ + 1: { + RawBalance: "1000000000000000000", + Balance: nil, + Address: testAccAddress1, + ChainID: 1, + HasError: false, + }, + }, + } + expectedTokens := map[common.Address][]token.StorageToken{ + testAccAddress1: {storageToken}, + } + + mockReader.EXPECT().FetchOrGetCachedWalletBalances(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedTokens, nil) + + service := &Service{ + rpcClient: c, + } + + api := &API{ + s: service, + reader: mockReader, + } + + forceRefresh := true + balances, err := api.FetchOrGetCachedWalletBalances(context.Background(), []common.Address{testTokenAddress1}, forceRefresh) + require.NoError(t, err) + require.NotNil(t, balances) +} diff --git a/services/wallet/reader.go b/services/wallet/reader.go index 61ce11847..9fa2aaeb1 100644 --- a/services/wallet/reader.go +++ b/services/wallet/reader.go @@ -1,5 +1,7 @@ package wallet +//go:generate mockgen -package=mock_reader -source=reader.go -destination=mock/reader/reader.go + import ( "context" "math" @@ -42,6 +44,16 @@ func belongsToMandatoryTokens(symbol string) bool { return false } +type ReaderInterface interface { + Start() error + Stop() + Restart() error + FetchOrGetCachedWalletBalances(ctx context.Context, clients map[uint64]chain.ClientInterface, addresses []common.Address, forceRefresh bool) (map[common.Address][]token.StorageToken, error) + FetchBalances(ctx context.Context, clients map[uint64]chain.ClientInterface, addresses []common.Address) (map[common.Address][]token.StorageToken, error) + GetCachedBalances(clients map[uint64]chain.ClientInterface, addresses []common.Address) (map[common.Address][]token.StorageToken, error) + GetLastTokenUpdateTimestamps() map[common.Address]int64 +} + func NewReader(tokenManager token.ManagerInterface, marketManager *market.Manager, persistence token.TokenBalancesStorage, walletFeed *event.Feed) *Reader { return &Reader{ tokenManager: tokenManager,