feat: get wallet api (#2619)
This commit is contained in:
parent
017ae1e205
commit
e199ddbe9d
|
@ -510,6 +510,10 @@ func (db *Database) GetPreferredUsername() (string, error) {
|
||||||
return db.makeSelectString(PreferredName)
|
return db.makeSelectString(PreferredName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *Database) GetCurrency() (string, error) {
|
||||||
|
return db.makeSelectString(Currency)
|
||||||
|
}
|
||||||
|
|
||||||
func (db *Database) GetInstalledStickerPacks() (rst *json.RawMessage, err error) {
|
func (db *Database) GetInstalledStickerPacks() (rst *json.RawMessage, err error) {
|
||||||
err = db.makeSelectRow(StickersPacksInstalled).Scan(&rst)
|
err = db.makeSelectRow(StickersPacksInstalled).Scan(&rst)
|
||||||
return
|
return
|
||||||
|
|
|
@ -124,7 +124,7 @@ func (b *StatusNode) initServices(config *params.NodeConfig) error {
|
||||||
if len(openseaKey) == 0 {
|
if len(openseaKey) == 0 {
|
||||||
openseaKey = OpenseaKeyFromEnv
|
openseaKey = OpenseaKeyFromEnv
|
||||||
}
|
}
|
||||||
walletService := b.walletService(accountsFeed, openseaKey)
|
walletService := b.walletService(accDB, accountsFeed, openseaKey)
|
||||||
services = append(services, walletService)
|
services = append(services, walletService)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,9 +441,9 @@ func (b *StatusNode) appmetricsService() common.StatusService {
|
||||||
return b.appMetricsSrvc
|
return b.appMetricsSrvc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *StatusNode) walletService(accountsFeed *event.Feed, openseaAPIKey string) common.StatusService {
|
func (b *StatusNode) walletService(accountsDB *accounts.Database, accountsFeed *event.Feed, openseaAPIKey string) common.StatusService {
|
||||||
if b.walletSrvc == nil {
|
if b.walletSrvc == nil {
|
||||||
b.walletSrvc = wallet.NewService(b.appDB, b.rpcClient, accountsFeed, openseaAPIKey)
|
b.walletSrvc = wallet.NewService(b.appDB, accountsDB, b.rpcClient, accountsFeed, openseaAPIKey)
|
||||||
}
|
}
|
||||||
return b.walletSrvc
|
return b.walletSrvc
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,22 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewAPI(s *Service) *API {
|
func NewAPI(s *Service) *API {
|
||||||
return &API{s}
|
r := NewReader(s)
|
||||||
|
return &API{s, r}
|
||||||
}
|
}
|
||||||
|
|
||||||
// API is class with methods available over RPC.
|
// API is class with methods available over RPC.
|
||||||
type API struct {
|
type API struct {
|
||||||
s *Service
|
s *Service
|
||||||
|
r *Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) StartWallet(ctx context.Context, chainIDs []uint64) error {
|
||||||
|
return api.r.Start(ctx, chainIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) GetWallet(ctx context.Context, chainIDs []uint64) (*Wallet, error) {
|
||||||
|
return api.r.GetWallet(ctx, chainIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetInitialBlocksRange sets initial blocks range
|
// SetInitialBlocksRange sets initial blocks range
|
||||||
|
@ -139,7 +149,7 @@ func (api *API) DeleteCustomTokenByChainID(ctx context.Context, chainID uint64,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetSavedAddresses(ctx context.Context) ([]*SavedAddress, error) {
|
func (api *API) GetSavedAddresses(ctx context.Context) ([]SavedAddress, error) {
|
||||||
log.Debug("call to get saved addresses")
|
log.Debug("call to get saved addresses")
|
||||||
rst, err := api.s.savedAddressesManager.GetSavedAddresses(api.s.rpcClient.UpstreamChainID)
|
rst, err := api.s.savedAddressesManager.GetSavedAddresses(api.s.rpcClient.UpstreamChainID)
|
||||||
log.Debug("result from database for saved addresses", "len", len(rst))
|
log.Debug("result from database for saved addresses", "len", len(rst))
|
||||||
|
@ -231,7 +241,7 @@ func (api *API) WatchTransactionByChainID(ctx context.Context, chainID uint64, t
|
||||||
return api.s.transactionManager.watch(ctx, transactionHash, chainClient)
|
return api.s.transactionManager.watch(ctx, transactionHash, chainClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) GetFavourites(ctx context.Context) ([]*Favourite, error) {
|
func (api *API) GetFavourites(ctx context.Context) ([]Favourite, error) {
|
||||||
log.Debug("call to get favourites")
|
log.Debug("call to get favourites")
|
||||||
rst, err := api.s.favouriteManager.GetFavourites()
|
rst, err := api.s.favouriteManager.GetFavourites()
|
||||||
log.Debug("result from database for favourites", "len", len(rst))
|
log.Debug("result from database for favourites", "len", len(rst))
|
||||||
|
|
|
@ -15,16 +15,16 @@ type FavouriteManager struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fm *FavouriteManager) GetFavourites() ([]*Favourite, error) {
|
func (fm *FavouriteManager) GetFavourites() ([]Favourite, error) {
|
||||||
rows, err := fm.db.Query(`SELECT address, name FROM favourites`)
|
rows, err := fm.db.Query(`SELECT address, name FROM favourites`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var rst []*Favourite
|
var rst []Favourite
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
favourite := &Favourite{}
|
favourite := Favourite{}
|
||||||
err := rows.Scan(&favourite.Address, &favourite.Name)
|
err := rows.Scan(&favourite.Address, &favourite.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -0,0 +1,226 @@
|
||||||
|
package wallet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
|
"github.com/status-im/status-go/services/wallet/chain"
|
||||||
|
"github.com/status-im/status-go/services/wallet/transfer"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewReader(s *Service) *Reader {
|
||||||
|
return &Reader{s}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Reader struct {
|
||||||
|
s *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReaderToken struct {
|
||||||
|
Token *Token `json:"token"`
|
||||||
|
OraclePrice float64 `json:"oraclePrice"`
|
||||||
|
CryptoBalance *hexutil.Big `json:"cryptoBalance"`
|
||||||
|
FiatBalance *big.Float `json:"fiatBalance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReaderAccount struct {
|
||||||
|
Account *accounts.Account `json:"account"`
|
||||||
|
Collections map[uint64][]OpenseaCollection `json:"collections"`
|
||||||
|
Tokens map[uint64][]ReaderToken `json:"tokens"`
|
||||||
|
Transactions map[uint64][]transfer.View `json:"transactions"`
|
||||||
|
|
||||||
|
FiatBalance *big.Float `json:"fiatBalance"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Wallet struct {
|
||||||
|
Accounts []ReaderAccount `json:"accounts"`
|
||||||
|
Favorites []Favourite `json:"favorites"`
|
||||||
|
OnRamp []CryptoOnRamp `json:"onRamp"`
|
||||||
|
SavedAddresses map[uint64][]SavedAddress `json:"savedAddresses"`
|
||||||
|
Tokens map[uint64][]*Token `json:"tokens"`
|
||||||
|
CustomTokens []*Token `json:"customTokens"`
|
||||||
|
PendingTransactions map[uint64][]*PendingTransaction `json:"pendingTransactions"`
|
||||||
|
|
||||||
|
FiatBalance *big.Float `json:"fiatBalance"`
|
||||||
|
Currency string `json:"currency"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAddresses(accounts []accounts.Account) []common.Address {
|
||||||
|
addresses := make([]common.Address, len(accounts))
|
||||||
|
for _, account := range accounts {
|
||||||
|
addresses = append(addresses, common.Address(account.Address))
|
||||||
|
}
|
||||||
|
return addresses
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) buildReaderAccount(
|
||||||
|
ctx context.Context,
|
||||||
|
chainIDs []uint64,
|
||||||
|
account accounts.Account,
|
||||||
|
visibleTokens map[uint64][]*Token,
|
||||||
|
prices map[string]float64,
|
||||||
|
balances map[common.Address]*hexutil.Big,
|
||||||
|
) (ReaderAccount, error) {
|
||||||
|
limit := (*hexutil.Big)(big.NewInt(20))
|
||||||
|
toBlock := (*hexutil.Big)(big.NewInt(0))
|
||||||
|
|
||||||
|
collections := make(map[uint64][]OpenseaCollection)
|
||||||
|
tokens := make(map[uint64][]ReaderToken)
|
||||||
|
transactions := make(map[uint64][]transfer.View)
|
||||||
|
accountFiatBalance := big.NewFloat(0)
|
||||||
|
for _, chainID := range chainIDs {
|
||||||
|
client, err := newOpenseaClient(chainID, r.s.openseaAPIKey)
|
||||||
|
if err == nil {
|
||||||
|
c, _ := client.fetchAllCollectionsByOwner(common.Address(account.Address))
|
||||||
|
collections[chainID] = c
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, token := range visibleTokens[chainID] {
|
||||||
|
oraclePrice := prices[token.Symbol]
|
||||||
|
cryptoBalance := balances[token.Address].ToInt()
|
||||||
|
fiatBalance := big.NewFloat(0).Mul(big.NewFloat(oraclePrice), new(big.Float).SetInt(cryptoBalance))
|
||||||
|
tokens[chainID] = append(tokens[chainID], ReaderToken{
|
||||||
|
Token: token,
|
||||||
|
OraclePrice: oraclePrice,
|
||||||
|
CryptoBalance: balances[token.Address],
|
||||||
|
FiatBalance: fiatBalance,
|
||||||
|
})
|
||||||
|
accountFiatBalance = accountFiatBalance.Add(accountFiatBalance, fiatBalance)
|
||||||
|
}
|
||||||
|
t, err := r.s.transferController.GetTransfersByAddress(ctx, chainID, common.Address(account.Address), toBlock, limit, false)
|
||||||
|
if err == nil {
|
||||||
|
transactions[chainID] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ReaderAccount{
|
||||||
|
Account: &account,
|
||||||
|
Collections: collections,
|
||||||
|
Tokens: tokens,
|
||||||
|
Transactions: transactions,
|
||||||
|
FiatBalance: accountFiatBalance,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) Start(ctx context.Context, chainIDs []uint64) error {
|
||||||
|
accounts, err := r.s.accountsDB.GetAccounts()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.s.transferController.CheckRecentHistory(chainIDs, getAddresses(accounts))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) GetWallet(ctx context.Context, chainIDs []uint64) (*Wallet, error) {
|
||||||
|
currency, err := r.s.accountsDB.GetCurrency()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tokensMap := make(map[uint64][]*Token)
|
||||||
|
for _, chainID := range chainIDs {
|
||||||
|
tokens, err := r.s.tokenManager.getTokens(chainID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tokensMap[chainID] = tokens
|
||||||
|
}
|
||||||
|
|
||||||
|
customTokens, err := r.s.tokenManager.getCustoms()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
visibleTokens, err := r.s.tokenManager.getVisible(chainIDs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenAddresses := make([]common.Address, 0)
|
||||||
|
tokenSymbols := make([]string, 0)
|
||||||
|
for _, tokens := range visibleTokens {
|
||||||
|
for _, token := range tokens {
|
||||||
|
tokenAddresses = append(tokenAddresses, token.Address)
|
||||||
|
tokenSymbols = append(tokenSymbols, token.Symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accounts, err := r.s.accountsDB.GetAccounts()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
prices, err := fetchCryptoComparePrices(tokenSymbols, currency)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
clients, err := chain.NewClients(r.s.rpcClient, chainIDs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
balances, err := r.s.tokenManager.getBalances(ctx, clients, getAddresses(accounts), tokenAddresses)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
readerAccounts := make([]ReaderAccount, len(accounts))
|
||||||
|
walletFiatBalance := big.NewFloat(0)
|
||||||
|
for i, account := range accounts {
|
||||||
|
readerAccount, err := r.buildReaderAccount(
|
||||||
|
ctx,
|
||||||
|
chainIDs,
|
||||||
|
account,
|
||||||
|
visibleTokens,
|
||||||
|
prices,
|
||||||
|
balances[common.Address(account.Address)],
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
walletFiatBalance = walletFiatBalance.Add(walletFiatBalance, readerAccount.FiatBalance)
|
||||||
|
readerAccounts[i] = readerAccount
|
||||||
|
}
|
||||||
|
|
||||||
|
savedAddressesMap := make(map[uint64][]SavedAddress)
|
||||||
|
for _, chainID := range chainIDs {
|
||||||
|
savedAddresses, err := r.s.savedAddressesManager.GetSavedAddresses(chainID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
savedAddressesMap[chainID] = savedAddresses
|
||||||
|
}
|
||||||
|
|
||||||
|
onRamp, err := r.s.cryptoOnRampManager.Get()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
favorites, err := r.s.favouriteManager.GetFavourites()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingTransactions := make(map[uint64][]*PendingTransaction)
|
||||||
|
for _, chainID := range chainIDs {
|
||||||
|
pendingTx, err := r.s.transactionManager.getAllPendings(chainID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pendingTransactions[chainID] = pendingTx
|
||||||
|
}
|
||||||
|
return &Wallet{
|
||||||
|
Accounts: readerAccounts,
|
||||||
|
Favorites: favorites,
|
||||||
|
OnRamp: onRamp,
|
||||||
|
SavedAddresses: savedAddressesMap,
|
||||||
|
Tokens: tokensMap,
|
||||||
|
CustomTokens: customTokens,
|
||||||
|
PendingTransactions: pendingTransactions,
|
||||||
|
Currency: currency,
|
||||||
|
FiatBalance: walletFiatBalance,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -18,16 +18,16 @@ type SavedAddressesManager struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sam *SavedAddressesManager) GetSavedAddresses(chainID uint64) ([]*SavedAddress, error) {
|
func (sam *SavedAddressesManager) GetSavedAddresses(chainID uint64) ([]SavedAddress, error) {
|
||||||
rows, err := sam.db.Query("SELECT address, name, network_id FROM saved_addresses WHERE network_id = ?", chainID)
|
rows, err := sam.db.Query("SELECT address, name, network_id FROM saved_addresses WHERE network_id = ?", chainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
var rst []*SavedAddress
|
var rst []SavedAddress
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
sa := &SavedAddress{}
|
sa := SavedAddress{}
|
||||||
err := rows.Scan(&sa.Address, &sa.Name, &sa.ChainID)
|
err := rows.Scan(&sa.Address, &sa.Name, &sa.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -43,7 +43,7 @@ func TestSavedAddresses(t *testing.T) {
|
||||||
rst, err = manager.GetSavedAddresses(777)
|
rst, err = manager.GetSavedAddresses(777)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 1, len(rst))
|
require.Equal(t, 1, len(rst))
|
||||||
require.Equal(t, sa, *rst[0])
|
require.Equal(t, sa, rst[0])
|
||||||
|
|
||||||
err = manager.DeleteSavedAddress(777, sa.Address)
|
err = manager.DeleteSavedAddress(777, sa.Address)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -8,12 +8,13 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
gethrpc "github.com/ethereum/go-ethereum/rpc"
|
gethrpc "github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||||
"github.com/status-im/status-go/rpc"
|
"github.com/status-im/status-go/rpc"
|
||||||
"github.com/status-im/status-go/services/wallet/transfer"
|
"github.com/status-im/status-go/services/wallet/transfer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewService initializes service instance.
|
// NewService initializes service instance.
|
||||||
func NewService(db *sql.DB, rpcClient *rpc.Client, accountFeed *event.Feed, openseaAPIKey string) *Service {
|
func NewService(db *sql.DB, accountsDB *accounts.Database, rpcClient *rpc.Client, accountFeed *event.Feed, openseaAPIKey string) *Service {
|
||||||
cryptoOnRampManager := NewCryptoOnRampManager(&CryptoOnRampOptions{
|
cryptoOnRampManager := NewCryptoOnRampManager(&CryptoOnRampOptions{
|
||||||
dataSourceType: DataSourceStatic,
|
dataSourceType: DataSourceStatic,
|
||||||
})
|
})
|
||||||
|
@ -24,6 +25,8 @@ func NewService(db *sql.DB, rpcClient *rpc.Client, accountFeed *event.Feed, open
|
||||||
transferController := transfer.NewTransferController(db, rpcClient, accountFeed)
|
transferController := transfer.NewTransferController(db, rpcClient, accountFeed)
|
||||||
|
|
||||||
return &Service{
|
return &Service{
|
||||||
|
db: db,
|
||||||
|
accountsDB: accountsDB,
|
||||||
rpcClient: rpcClient,
|
rpcClient: rpcClient,
|
||||||
favouriteManager: favouriteManager,
|
favouriteManager: favouriteManager,
|
||||||
tokenManager: tokenManager,
|
tokenManager: tokenManager,
|
||||||
|
@ -38,6 +41,8 @@ func NewService(db *sql.DB, rpcClient *rpc.Client, accountFeed *event.Feed, open
|
||||||
|
|
||||||
// Service is a wallet service.
|
// Service is a wallet service.
|
||||||
type Service struct {
|
type Service struct {
|
||||||
|
db *sql.DB
|
||||||
|
accountsDB *accounts.Database
|
||||||
rpcClient *rpc.Client
|
rpcClient *rpc.Client
|
||||||
savedAddressesManager *SavedAddressesManager
|
savedAddressesManager *SavedAddressesManager
|
||||||
tokenManager *TokenManager
|
tokenManager *TokenManager
|
||||||
|
|
|
@ -242,6 +242,21 @@ func (tm *TokenManager) deleteCustom(chainID uint64, address common.Address) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tm *TokenManager) getTokenBalance(ctx context.Context, client *chain.Client, account common.Address, token common.Address) (*big.Int, error) {
|
||||||
|
caller, err := ierc20.NewIERC20Caller(token, client)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return caller.BalanceOf(&bind.CallOpts{
|
||||||
|
Context: ctx,
|
||||||
|
}, account)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TokenManager) getChainBalance(ctx context.Context, client *chain.Client, account common.Address) (*big.Int, error) {
|
||||||
|
return client.BalanceAt(ctx, account, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (tm *TokenManager) getBalances(parent context.Context, clients []*chain.Client, accounts, tokens []common.Address) (map[common.Address]map[common.Address]*hexutil.Big, error) {
|
func (tm *TokenManager) getBalances(parent context.Context, clients []*chain.Client, accounts, tokens []common.Address) (map[common.Address]map[common.Address]*hexutil.Big, error) {
|
||||||
var (
|
var (
|
||||||
group = async.NewAtomicGroup(parent)
|
group = async.NewAtomicGroup(parent)
|
||||||
|
@ -250,10 +265,6 @@ func (tm *TokenManager) getBalances(parent context.Context, clients []*chain.Cli
|
||||||
)
|
)
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
for tokenIdx := range tokens {
|
for tokenIdx := range tokens {
|
||||||
caller, err := ierc20.NewIERC20Caller(tokens[tokenIdx], client)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for accountIdx := range accounts {
|
for accountIdx := range accounts {
|
||||||
// Below, we set account and token from idx on purpose to avoid override
|
// Below, we set account and token from idx on purpose to avoid override
|
||||||
account := accounts[accountIdx]
|
account := accounts[accountIdx]
|
||||||
|
@ -261,9 +272,14 @@ func (tm *TokenManager) getBalances(parent context.Context, clients []*chain.Cli
|
||||||
group.Add(func(parent context.Context) error {
|
group.Add(func(parent context.Context) error {
|
||||||
ctx, cancel := context.WithTimeout(parent, requestTimeout)
|
ctx, cancel := context.WithTimeout(parent, requestTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
balance, err := caller.BalanceOf(&bind.CallOpts{
|
var balance *big.Int
|
||||||
Context: ctx,
|
var err error
|
||||||
}, account)
|
if token == common.HexToAddress("0x") {
|
||||||
|
balance, err = tm.getChainBalance(ctx, client, account)
|
||||||
|
} else {
|
||||||
|
balance, err = tm.getTokenBalance(ctx, client, account, token)
|
||||||
|
}
|
||||||
|
|
||||||
// We don't want to return an error here and prevent
|
// We don't want to return an error here and prevent
|
||||||
// the rest from completing
|
// the rest from completing
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue