chore_: CHERRY-PICK Proxy URLs for blockchain providers (#5644)

* feat(wallet)_: add basic auth for cryptocompare proxy (#5536)

* feat(wallet)_: add basic auth for cryptocompare proxy

* test(wallet)_: add a test for httpclient used in market clients

* feat(wallet)_: add status proxy RPC urls for blockchain providers

Replace the status proxy URL for cryptocompare.
This commit is contained in:
IvanBelyakoff 2024-08-01 11:06:34 +02:00 committed by GitHub
parent 8dcaf21576
commit e16d820ecd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 430 additions and 125 deletions

View File

@ -61,6 +61,11 @@ GIT_AUTHOR := $(shell git config user.email || echo $$USER)
ENABLE_METRICS ?= true
BUILD_TAGS ?= gowaku_no_rln
ifdef RELEASE
BUILD_TAGS += release
endif
BUILD_FLAGS ?= -ldflags="-X github.com/status-im/status-go/params.Version=$(RELEASE_TAG:v%=%) \
-X github.com/status-im/status-go/params.GitCommit=$(GIT_COMMIT) \
-X github.com/status-im/status-go/params.IpfsGatewayURL=$(IPFS_GATEWAY_URL) \

View File

@ -1,9 +1,11 @@
package api
import (
"fmt"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/buildinfo"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/protocol/requests"
)
@ -27,6 +29,8 @@ var ganacheTokenAddress = common.HexToAddress("0x8571Ddc46b10d31EF963aF49b6C7799
var mainnet = params.Network{
ChainID: mainnetChainID,
ChainName: "Mainnet",
DefaultRPCURL: fmt.Sprintf("https://%s.api.status.im/grove/ethereum/mainnet/", buildinfo.ApiProxyStageName),
DefaultFallbackURL: fmt.Sprintf("https://%s.api.status.im/infura/ethereum/mainnet/", buildinfo.ApiProxyStageName),
RPCURL: "https://eth-archival.rpc.grove.city/v1/",
FallbackURL: "https://mainnet.infura.io/v3/",
BlockExplorerURL: "https://etherscan.io/",
@ -63,6 +67,8 @@ var goerli = params.Network{
var sepolia = params.Network{
ChainID: sepoliaChainID,
ChainName: "Mainnet",
DefaultRPCURL: fmt.Sprintf("https://%s.api.status.im/grove/ethereum/sepolia/", buildinfo.ApiProxyStageName),
DefaultFallbackURL: fmt.Sprintf("https://%s.api.status.im/infura/ethereum/sepolia/", buildinfo.ApiProxyStageName),
RPCURL: "https://sepolia-archival.rpc.grove.city/v1/",
FallbackURL: "https://sepolia.infura.io/v3/",
BlockExplorerURL: "https://sepolia.etherscan.io/",
@ -81,7 +87,9 @@ var sepolia = params.Network{
var optimism = params.Network{
ChainID: optimismChainID,
ChainName: "Optimism",
RPCURL: "https://optimism-mainnet.rpc.grove.city/v1/",
DefaultRPCURL: fmt.Sprintf("https://%s.api.status.im/grove/optimism/mainnet/", buildinfo.ApiProxyStageName),
DefaultFallbackURL: fmt.Sprintf("https://%s.api.status.im/infura/optimism/mainnet/", buildinfo.ApiProxyStageName),
RPCURL: "https://optimism-archival.rpc.grove.city/v1/",
FallbackURL: "https://optimism-mainnet.infura.io/v3/",
BlockExplorerURL: "https://optimistic.etherscan.io",
IconURL: "network/Network=Optimism",
@ -117,6 +125,8 @@ var optimismGoerli = params.Network{
var optimismSepolia = params.Network{
ChainID: optimismSepoliaChainID,
ChainName: "Optimism",
DefaultRPCURL: fmt.Sprintf("https://%s.api.status.im/grove/optimism/sepolia/", buildinfo.ApiProxyStageName),
DefaultFallbackURL: fmt.Sprintf("https://%s.api.status.im/infura/optimism/sepolia/", buildinfo.ApiProxyStageName),
RPCURL: "https://optimism-sepolia-archival.rpc.grove.city/v1/",
FallbackURL: "https://optimism-sepolia.infura.io/v3/",
BlockExplorerURL: "https://sepolia-optimism.etherscan.io/",
@ -135,6 +145,8 @@ var optimismSepolia = params.Network{
var arbitrum = params.Network{
ChainID: arbitrumChainID,
ChainName: "Arbitrum",
DefaultRPCURL: fmt.Sprintf("https://%s.api.status.im/grove/arbitrum/mainnet/", buildinfo.ApiProxyStageName),
DefaultFallbackURL: fmt.Sprintf("https://%s.api.status.im/infura/arbitrum/mainnet/", buildinfo.ApiProxyStageName),
RPCURL: "https://arbitrum-one.rpc.grove.city/v1/",
FallbackURL: "https://arbitrum-mainnet.infura.io/v3/",
BlockExplorerURL: "https://arbiscan.io/",
@ -171,6 +183,8 @@ var arbitrumGoerli = params.Network{
var arbitrumSepolia = params.Network{
ChainID: arbitrumSepoliaChainID,
ChainName: "Arbitrum",
DefaultRPCURL: fmt.Sprintf("https://%s.api.status.im/grove/arbitrum/sepolia/", buildinfo.ApiProxyStageName),
DefaultFallbackURL: fmt.Sprintf("https://%s.api.status.im/infura/arbitrum/sepolia/", buildinfo.ApiProxyStageName),
RPCURL: "https://arbitrum-sepolia-archival.rpc.grove.city/v1/",
FallbackURL: "https://arbitrum-sepolia.infura.io/v3/",
BlockExplorerURL: "https://sepolia-explorer.arbitrum.io/",

View File

@ -161,7 +161,7 @@ func SetFleet(fleet string, nodeConfig *params.NodeConfig) error {
return nil
}
func buildWalletConfig(request *requests.WalletSecretsConfig) params.WalletConfig {
func buildWalletConfig(request *requests.WalletSecretsConfig, statusProxyEnabled bool) params.WalletConfig {
walletConfig := params.WalletConfig{
Enabled: true,
AlchemyAPIKeys: make(map[uint64]string),
@ -214,6 +214,20 @@ func buildWalletConfig(request *requests.WalletSecretsConfig) params.WalletConfi
if request.AlchemyOptimismSepoliaToken != "" {
walletConfig.AlchemyAPIKeys[optimismSepoliaChainID] = request.AlchemyOptimismSepoliaToken
}
if request.StatusProxyMarketUser != "" {
walletConfig.StatusProxyMarketUser = request.StatusProxyMarketUser
}
if request.StatusProxyMarketPassword != "" {
walletConfig.StatusProxyMarketPassword = request.StatusProxyMarketPassword
}
if request.StatusProxyBlockchainUser != "" {
walletConfig.StatusProxyBlockchainUser = request.StatusProxyBlockchainUser
}
if request.StatusProxyBlockchainPassword != "" {
walletConfig.StatusProxyBlockchainPassword = request.StatusProxyBlockchainPassword
}
walletConfig.StatusProxyEnabled = statusProxyEnabled
return walletConfig
}
@ -281,7 +295,7 @@ func defaultNodeConfig(installationID string, request *requests.CreateAccount, o
nodeConfig.MaxPeers = DefaultMaxPeers
nodeConfig.MaxPendingPeers = DefaultMaxPendingPeers
nodeConfig.WalletConfig = buildWalletConfig(&request.WalletSecretsConfig)
nodeConfig.WalletConfig = buildWalletConfig(&request.WalletSecretsConfig, request.StatusProxyEnabled)
nodeConfig.LocalNotificationsConfig = params.LocalNotificationsConfig{Enabled: true}
nodeConfig.BrowsersConfig = params.BrowsersConfig{Enabled: true}

View File

@ -601,7 +601,7 @@ func (b *GethStatusBackend) loginAccount(request *requests.Login) error {
KeycardPairingDataFile: DefaultKeycardPairingDataFile,
}
defaultCfg.WalletConfig = buildWalletConfig(&request.WalletSecretsConfig)
defaultCfg.WalletConfig = buildWalletConfig(&request.WalletSecretsConfig, request.StatusProxyEnabled)
err = b.UpdateNodeConfigFleet(acc, request.Password, defaultCfg)
if err != nil {

View File

@ -0,0 +1,5 @@
//go:build !release
package buildinfo
var ApiProxyStageName = "test"

View File

@ -0,0 +1,5 @@
//go:build release
package buildinfo
var ApiProxyStageName = "prod"

View File

@ -314,7 +314,20 @@ func (n *StatusNode) setupRPCClient() (err error) {
if err != nil {
return
}
n.rpcClient, err = rpc.NewClient(gethNodeClient, n.config.NetworkID, n.config.UpstreamConfig, n.config.Networks, n.appDB)
// ProviderConfigs should be passed not in wallet secrets config on login
// but some other way, as it's not wallet specific and should not be passed with login request
// but currently there is no other way to pass it
providerConfigs := []params.ProviderConfig{
{
Enabled: n.config.WalletConfig.StatusProxyEnabled,
Name: rpc.ProviderStatusProxy,
User: n.config.WalletConfig.StatusProxyBlockchainUser,
Password: n.config.WalletConfig.StatusProxyBlockchainPassword,
},
}
n.rpcClient, err = rpc.NewClient(gethNodeClient, n.config.NetworkID, n.config.UpstreamConfig, n.config.Networks, n.appDB, providerConfigs)
if err != nil {
return
}

View File

@ -310,6 +310,21 @@ type UpstreamRPCConfig struct {
URL string
}
type ProviderConfig struct {
// Enabled flag specifies whether feature is enabled
Enabled bool `validate:"required"`
// To identify provider
Name string `validate:"required"`
// URL sets the rpc upstream host address for communication with
// a non-local infura endpoint.
User string `json:",omitempty"`
Password string `json:",omitempty"`
APIKey string `json:"APIKey,omitempty"`
APIKeySecret string `json:"APIKeySecret,omitempty"`
}
// ----------
// NodeConfig
// ----------
@ -531,6 +546,8 @@ type TokenOverride struct {
type Network struct {
ChainID uint64 `json:"chainId"`
ChainName string `json:"chainName"`
DefaultRPCURL string `json:"defaultRpcUrl"` // proxy rpc url
DefaultFallbackURL string `json:"defaultFallbackURL"` // proxy fallback url
RPCURL string `json:"rpcUrl"`
OriginalRPCURL string `json:"originalRpcUrl"`
FallbackURL string `json:"fallbackURL"`
@ -551,14 +568,19 @@ type Network struct {
// WalletConfig extra configuration for wallet.Service.
type WalletConfig struct {
Enabled bool
OpenseaAPIKey string `json:"OpenseaAPIKey"`
RaribleMainnetAPIKey string `json:"RaribleMainnetAPIKey"`
RaribleTestnetAPIKey string `json:"RaribleTestnetAPIKey"`
AlchemyAPIKeys map[uint64]string `json:"AlchemyAPIKeys"`
InfuraAPIKey string `json:"InfuraAPIKey"`
InfuraAPIKeySecret string `json:"InfuraAPIKeySecret"`
EnableCelerBridge bool `json:"EnableCelerBridge"`
Enabled bool
OpenseaAPIKey string `json:"OpenseaAPIKey"`
RaribleMainnetAPIKey string `json:"RaribleMainnetAPIKey"`
RaribleTestnetAPIKey string `json:"RaribleTestnetAPIKey"`
AlchemyAPIKeys map[uint64]string `json:"AlchemyAPIKeys"`
InfuraAPIKey string `json:"InfuraAPIKey"`
InfuraAPIKeySecret string `json:"InfuraAPIKeySecret"`
StatusProxyMarketUser string `json:"StatusProxyMarketUser"`
StatusProxyMarketPassword string `json:"StatusProxyMarketPassword"`
StatusProxyBlockchainUser string `json:"StatusProxyBlockchainUser"`
StatusProxyBlockchainPassword string `json:"StatusProxyBlockchainPassword"`
StatusProxyEnabled bool `json:"StatusProxyEnabled"`
EnableCelerBridge bool `json:"EnableCelerBridge"`
}
// LocalNotificationsConfig extra configuration for localnotifications.Service.

View File

@ -86,6 +86,7 @@ type CreateAccount struct {
KeycardInstanceUID string `json:"keycardInstanceUID"`
KeycardPairingDataFile *string `json:"keycardPairingDataFile"`
StatusProxyEnabled bool `json:"statusProxyEnabled"`
}
type WalletSecretsConfig struct {
@ -96,17 +97,22 @@ type WalletSecretsConfig struct {
RaribleMainnetAPIKey string `json:"raribleMainnetApiKey"`
RaribleTestnetAPIKey string `json:"raribleTestnetApiKey"`
AlchemyEthereumMainnetToken string `json:"alchemyEthereumMainnetToken"`
AlchemyEthereumGoerliToken string `json:"alchemyEthereumGoerliToken"`
AlchemyEthereumSepoliaToken string `json:"alchemyEthereumSepoliaToken"`
AlchemyArbitrumMainnetToken string `json:"alchemyArbitrumMainnetToken"`
AlchemyArbitrumGoerliToken string `json:"alchemyArbitrumGoerliToken"`
AlchemyArbitrumSepoliaToken string `json:"alchemyArbitrumSepoliaToken"`
AlchemyOptimismMainnetToken string `json:"alchemyOptimismMainnetToken"`
AlchemyOptimismGoerliToken string `json:"alchemyOptimismGoerliToken"`
AlchemyOptimismSepoliaToken string `json:"alchemyOptimismSepoliaToken"`
StatusProxyMarketUser string `json:"statusProxyMarketUser"`
StatusProxyMarketPassword string `json:"statusProxyMarketPassword"`
StatusProxyBlockchainUser string `json:"statusProxyBlockchainUser"`
StatusProxyBlockchainPassword string `json:"statusProxyBlockchainPassword"`
// Testing
GanacheURL string `json:"ganacheURL"`
AlchemyEthereumMainnetToken string `json:"alchemyEthereumMainnetToken"`
AlchemyEthereumGoerliToken string `json:"alchemyEthereumGoerliToken"`
AlchemyEthereumSepoliaToken string `json:"alchemyEthereumSepoliaToken"`
AlchemyArbitrumMainnetToken string `json:"alchemyArbitrumMainnetToken"`
AlchemyArbitrumGoerliToken string `json:"alchemyArbitrumGoerliToken"`
AlchemyArbitrumSepoliaToken string `json:"alchemyArbitrumSepoliaToken"`
AlchemyOptimismMainnetToken string `json:"alchemyOptimismMainnetToken"`
AlchemyOptimismGoerliToken string `json:"alchemyOptimismGoerliToken"`
AlchemyOptimismSepoliaToken string `json:"alchemyOptimismSepoliaToken"`
GanacheURL string `json:"ganacheURL"`
}
func (c *CreateAccount) Validate(validation *CreateAccountValidation) error {

View File

@ -35,7 +35,8 @@ type Login struct {
WalletSecretsConfig
APIConfig *APIConfig `json:"apiConfig"`
APIConfig *APIConfig `json:"apiConfig"`
StatusProxyEnabled bool `json:"statusProxyEnabled"`
}
func (c *Login) Validate() error {

View File

@ -3,12 +3,12 @@ package rpc
import (
"context"
"database/sql"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"net/url"
"reflect"
"strings"
"sync"
"time"
@ -26,6 +26,11 @@ import (
const (
// DefaultCallTimeout is a default timeout for an RPC call
DefaultCallTimeout = time.Minute
// Names of providers
providerGrove = "grove"
providerInfura = "infura"
ProviderStatusProxy = "status-proxy"
)
// List of RPC client errors.
@ -67,7 +72,8 @@ type Client struct {
handlers map[string]Handler // locally registered handlers
log log.Logger
walletNotifier func(chainID uint64, message string)
walletNotifier func(chainID uint64, message string)
providerConfigs []params.ProviderConfig
}
// Is initialized in a build-tag-dependent module
@ -78,7 +84,7 @@ var verifProxyInitFn func(c *Client)
//
// Client is safe for concurrent use and will automatically
// reconnect to the server if connection is lost.
func NewClient(client *gethrpc.Client, upstreamChainID uint64, upstream params.UpstreamRPCConfig, networks []params.Network, db *sql.DB) (*Client, error) {
func NewClient(client *gethrpc.Client, upstreamChainID uint64, upstream params.UpstreamRPCConfig, networks []params.Network, db *sql.DB, providerConfigs []params.ProviderConfig) (*Client, error) {
var err error
log := log.New("package", "status-go/rpc.Client")
@ -99,6 +105,7 @@ func NewClient(client *gethrpc.Client, upstreamChainID uint64, upstream params.U
rpcClients: make(map[uint64]chain.ClientInterface),
limiterPerProvider: make(map[string]*chain.RPCRpsLimiter),
log: log,
providerConfigs: providerConfigs,
}
if upstream.Enabled {
@ -133,18 +140,6 @@ func (c *Client) SetWalletNotifier(notifier func(chainID uint64, message string)
c.walletNotifier = notifier
}
func extractLastParamFromURL(inputURL string) (string, error) {
parsedURL, err := url.Parse(inputURL)
if err != nil {
return "", err
}
pathSegments := strings.Split(parsedURL.Path, "/")
lastSegment := pathSegments[len(pathSegments)-1]
return lastSegment, nil
}
func extractHostAndPortFromURL(inputURL string) (string, error) {
parsedURL, err := url.Parse(inputURL)
if err != nil {
@ -154,21 +149,26 @@ func extractHostAndPortFromURL(inputURL string) (string, error) {
return parsedURL.Host, nil
}
func (c *Client) getRPCRpsLimiter(URL string) (*chain.RPCRpsLimiter, error) {
apiKey, err := extractLastParamFromURL(URL)
if err != nil {
return nil, err
}
func (c *Client) getRPCRpsLimiter(key string) (*chain.RPCRpsLimiter, error) {
c.rpsLimiterMutex.Lock()
defer c.rpsLimiterMutex.Unlock()
if limiter, ok := c.limiterPerProvider[apiKey]; ok {
if limiter, ok := c.limiterPerProvider[key]; ok {
return limiter, nil
}
limiter := chain.NewRPCRpsLimiter()
c.limiterPerProvider[apiKey] = limiter
c.limiterPerProvider[key] = limiter
return limiter, nil
}
func getProviderConfig(providerConfigs []params.ProviderConfig, providerName string) (params.ProviderConfig, error) {
for _, providerConfig := range providerConfigs {
if providerConfig.Name == providerName {
return providerConfig, nil
}
}
return params.ProviderConfig{}, fmt.Errorf("provider config not found for provider: %s", providerName)
}
func (c *Client) getClientUsingCache(chainID uint64) (chain.ClientInterface, error) {
c.rpcClientsMutex.Lock()
defer c.rpcClientsMutex.Unlock()
@ -187,45 +187,9 @@ func (c *Client) getClientUsingCache(chainID uint64) (chain.ClientInterface, err
return nil, fmt.Errorf("could not find network: %d", chainID)
}
rpcClient, err := gethrpc.Dial(network.RPCURL)
if err != nil {
return nil, fmt.Errorf("dial upstream server: %s", err)
}
rpcLimiter, err := c.getRPCRpsLimiter(network.RPCURL)
if err != nil {
return nil, fmt.Errorf("get RPC limiter: %s", err)
}
hostPortMain, err := extractHostAndPortFromURL(network.RPCURL)
if err != nil {
hostPortMain = "main"
}
ethClients := []*chain.EthClient{
chain.NewEthClient(ethclient.NewClient(rpcClient), rpcLimiter, rpcClient, hostPortMain),
}
var (
rpcFallbackClient *gethrpc.Client
rpcFallbackLimiter *chain.RPCRpsLimiter
)
if len(network.FallbackURL) > 0 {
rpcFallbackClient, err = gethrpc.Dial(network.FallbackURL)
if err != nil {
return nil, fmt.Errorf("dial upstream server: %s", err)
}
rpcFallbackLimiter, err = c.getRPCRpsLimiter(network.FallbackURL)
if err != nil {
return nil, fmt.Errorf("get RPC fallback limiter: %s", err)
}
hostPortFallback, err := extractHostAndPortFromURL(network.FallbackURL)
if err != nil {
hostPortFallback = "fallback"
}
ethClients = append(ethClients, chain.NewEthClient(ethclient.NewClient(rpcFallbackClient), rpcFallbackLimiter, rpcFallbackClient, hostPortFallback))
ethClients := c.getEthClents(network)
if len(ethClients) == 0 {
return nil, fmt.Errorf("could not find any RPC URL for chain: %d", chainID)
}
client := chain.NewClient(ethClients, chainID)
@ -234,6 +198,69 @@ func (c *Client) getClientUsingCache(chainID uint64) (chain.ClientInterface, err
return client, nil
}
func (c *Client) getEthClents(network *params.Network) []*chain.EthClient {
urls := make(map[string]string)
keys := make([]string, 0)
authMap := make(map[string]string)
// find proxy provider
proxyProvider, err := getProviderConfig(c.providerConfigs, ProviderStatusProxy)
if err != nil {
c.log.Warn("could not find provider config for status-proxy", "error", err)
}
if proxyProvider.Enabled {
key := ProviderStatusProxy
keyFallback := ProviderStatusProxy + "-fallback"
urls[key] = network.DefaultRPCURL
urls[keyFallback] = network.DefaultFallbackURL
keys = []string{key, keyFallback}
authMap[key] = proxyProvider.User + ":" + proxyProvider.Password
authMap[keyFallback] = authMap[key]
}
keys = append(keys, []string{"main", "fallback"}...)
urls["main"] = network.RPCURL
urls["fallback"] = network.FallbackURL
ethClients := make([]*chain.EthClient, 0)
for _, key := range keys {
var rpcClient *gethrpc.Client
var rpcLimiter *chain.RPCRpsLimiter
var err error
var hostPort string
url := urls[key]
if len(url) > 0 {
// For now we only support auth for status-proxy.
authStr, ok := authMap[key]
var opts []gethrpc.ClientOption
if ok {
authEncoded := base64.StdEncoding.EncodeToString([]byte(authStr))
opts = append(opts, gethrpc.WithHeader("Authorization", "Basic "+authEncoded))
}
rpcClient, err = gethrpc.DialOptions(context.Background(), url, opts...)
if err != nil {
c.log.Error("dial server "+key, "error", err)
}
hostPort, err = extractHostAndPortFromURL(url)
if err != nil {
hostPort = key
}
rpcLimiter, err = c.getRPCRpsLimiter(hostPort)
if err != nil {
c.log.Error("get RPC limiter "+key, "error", err)
}
ethClients = append(ethClients, chain.NewEthClient(ethclient.NewClient(rpcClient), rpcLimiter, rpcClient, hostPort))
}
}
return ethClients
}
// Ethclient returns ethclient.Client per chain
func (c *Client) EthClient(chainID uint64) (chain.ClientInterface, error) {
client, err := c.getClientUsingCache(chainID)

View File

@ -3,17 +3,22 @@ package rpc
import (
"context"
"database/sql"
"encoding/base64"
"fmt"
"math/big"
"net/http"
"net/http/httptest"
"sync"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/status-im/status-go/appdatabase"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/t/helpers"
"github.com/ethereum/go-ethereum/common"
gethrpc "github.com/ethereum/go-ethereum/rpc"
)
@ -39,7 +44,7 @@ func TestBlockedRoutesCall(t *testing.T) {
gethRPCClient, err := gethrpc.Dial(ts.URL)
require.NoError(t, err)
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
require.NoError(t, err)
for _, m := range blockedMethods {
@ -78,7 +83,7 @@ func TestBlockedRoutesRawCall(t *testing.T) {
gethRPCClient, err := gethrpc.Dial(ts.URL)
require.NoError(t, err)
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
require.NoError(t, err)
for _, m := range blockedMethods {
@ -105,7 +110,7 @@ func TestUpdateUpstreamURL(t *testing.T) {
gethRPCClient, err := gethrpc.Dial(ts.URL)
require.NoError(t, err)
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: true, URL: ts.URL}, []params.Network{}, db)
c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: true, URL: ts.URL}, []params.Network{}, db, nil)
require.NoError(t, err)
require.Equal(t, ts.URL, c.upstreamURL)
@ -132,3 +137,62 @@ func createTestServer(resp string) *httptest.Server {
fmt.Fprintln(w, resp)
}))
}
func TestGetClientsUsingCache(t *testing.T) {
db, close := setupTestNetworkDB(t)
defer close()
providerConfig := params.ProviderConfig{
Enabled: true,
Name: ProviderStatusProxy,
User: "user1",
Password: "pass1",
}
providerConfigs := []params.ProviderConfig{providerConfig}
var wg sync.WaitGroup
wg.Add(2) // 2 providers
// Create a new ServeMux
mux := http.NewServeMux()
path1 := "/foo"
path2 := "/bar"
// Register handlers for different URL paths
mux.HandleFunc(path1, func(w http.ResponseWriter, r *http.Request) {
authToken := base64.StdEncoding.EncodeToString([]byte(providerConfig.User + ":" + providerConfig.Password))
require.Equal(t, fmt.Sprintf("Basic %s", authToken), r.Header.Get("Authorization"))
wg.Done()
})
mux.HandleFunc(path2, func(w http.ResponseWriter, r *http.Request) {
authToken := base64.StdEncoding.EncodeToString([]byte(providerConfig.User + ":" + providerConfig.Password))
require.Equal(t, fmt.Sprintf("Basic %s", authToken), r.Header.Get("Authorization"))
wg.Done()
})
// Create a new server with the mux as the handler
server := httptest.NewServer(mux)
defer server.Close()
networks := []params.Network{
{
ChainID: 1,
DefaultRPCURL: server.URL + path1,
DefaultFallbackURL: server.URL + path2,
},
}
c, err := NewClient(nil, 1, params.UpstreamRPCConfig{}, networks, db, providerConfigs)
require.NoError(t, err)
// Networks from DB must pick up DefaultRPCURL and DefaultFallbackURL
chainClient, err := c.getClientUsingCache(networks[0].ChainID)
require.NoError(t, err)
require.NotNil(t, chainClient)
// Make any call to provider. If test finishes, then all handlers were called and asserts inside them passed
balance, err := chainClient.BalanceAt(context.TODO(), common.Address{0x1}, big.NewInt(1))
assert.Error(t, err) // EOF, we dont return anything from the server, because of error iterate over all providers
assert.Nil(t, balance)
wg.Wait()
}

View File

@ -169,6 +169,7 @@ func (nm *Manager) Init(networks []params.Network) error {
if err != nil {
errors += fmt.Sprintf("error updating network original url for ChainID: %d, %s", currentNetworks[j].ChainID, err.Error())
}
break
}
}
@ -230,12 +231,15 @@ func (nm *Manager) Find(chainID uint64) *params.Network {
if len(networks) != 1 || err != nil {
return nil
}
setDefaultRPCURL(networks, nm.configuredNetworks)
return networks[0]
}
func (nm *Manager) GetAll() ([]*params.Network, error) {
query := newNetworksQuery()
return query.exec(nm.db)
networks, err := query.exec(nm.db)
setDefaultRPCURL(networks, nm.configuredNetworks)
return networks, err
}
func (nm *Manager) Get(onlyEnabled bool) ([]*params.Network, error) {
@ -282,6 +286,12 @@ func (nm *Manager) Get(onlyEnabled bool) ([]*params.Network, error) {
continue
}
}
configuredNetwork, err := findNetwork(nm.configuredNetworks, network.ChainID)
if err != nil {
addDefaultRPCURL(network, configuredNetwork)
}
results = append(results, network)
}
@ -355,3 +365,28 @@ func (nm *Manager) GetActiveNetworks() ([]*params.Network, error) {
return availableNetworks, nil
}
func findNetwork(networks []params.Network, chainID uint64) (params.Network, error) {
for _, network := range networks {
if network.ChainID == chainID {
return network, nil
}
}
return params.Network{}, fmt.Errorf("network not found")
}
func addDefaultRPCURL(target *params.Network, source params.Network) {
target.DefaultRPCURL = source.DefaultRPCURL
target.DefaultFallbackURL = source.DefaultFallbackURL
}
func setDefaultRPCURL(target []*params.Network, source []params.Network) {
for i := range target {
for j := range source {
if target[i].ChainID == source[j].ChainID {
addDefaultRPCURL(target[i], source[j])
break
}
}
}
}

View File

@ -36,7 +36,7 @@ func setupTestAPI(t *testing.T) (*API, func()) {
}
client := gethrpc.DialInProc(server)
rpcClient, err := statusRPC.NewClient(client, 1, upstreamConfig, nil, db)
rpcClient, err := statusRPC.NewClient(client, 1, upstreamConfig, nil, db, nil)
require.NoError(t, err)
service := NewService(db, rpcClient, nil)

View File

@ -28,7 +28,7 @@ func TestNewService(t *testing.T) {
}
client := gethrpc.DialInProc(server)
rpcClient, err := statusRPC.NewClient(client, 1, upstreamConfig, nil, db)
rpcClient, err := statusRPC.NewClient(client, 1, upstreamConfig, nil, db, nil)
require.NoError(t, err)
service := NewService(db, rpcClient, rpcClient.NetworkManager)

View File

@ -40,7 +40,7 @@ func setupTestAPI(t *testing.T) (*API, func()) {
_ = client
rpcClient, err := statusRPC.NewClient(nil, 1, upstreamConfig, nil, db)
rpcClient, err := statusRPC.NewClient(nil, 1, upstreamConfig, nil, db, nil)
require.NoError(t, err)
// import account keys

View File

@ -405,7 +405,7 @@ func Test_removeBalanceHistoryOnEventAccountRemoved(t *testing.T) {
txServiceMockCtrl := gomock.NewController(t)
server, _ := fake.NewTestServer(txServiceMockCtrl)
client := gethrpc.DialInProc(server)
rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, appDB)
rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, appDB, nil)
rpcClient.UpstreamChainID = chainID
service := NewService(walletDB, accountsDB, &accountFeed, &walletFeed, rpcClient, nil, nil, nil)

View File

@ -85,7 +85,7 @@ func (s *CelerBridgeProcessor) estimateAmt(from, to *params.Network, amountIn *b
params.Add("slippage_tolerance", "500")
url := fmt.Sprintf("%s/v2/estimateAmt", base)
response, err := s.httpClient.DoGetRequest(context.Background(), url, params)
response, err := s.httpClient.DoGetRequest(context.Background(), url, params, nil)
if err != nil {
return nil, createBridgeCellerErrorResponse(err)
}
@ -112,7 +112,7 @@ func (s *CelerBridgeProcessor) getTransferConfig(isTest bool) (*cbridge.GetTrans
base = testBaseURL
}
url := fmt.Sprintf("%s/v2/getTransferConfigs", base)
response, err := s.httpClient.DoGetRequest(context.Background(), url, nil)
response, err := s.httpClient.DoGetRequest(context.Background(), url, nil, nil)
if err != nil {
return nil, createBridgeCellerErrorResponse(err)
}

View File

@ -422,7 +422,7 @@ func (h *HopBridgeProcessor) CalculateFees(params ProcessorInputParams) (*big.In
reqParams.Add("slippage", "0.5") // menas 0.5%
url := "https://api.hop.exchange/v1/quote"
response, err := h.httpClient.DoGetRequest(context.Background(), url, reqParams)
response, err := h.httpClient.DoGetRequest(context.Background(), url, reqParams, nil)
if err != nil {
return nil, nil, err
}

View File

@ -90,7 +90,7 @@ func setupTestNetworkDB(t *testing.T) (*sql.DB, func()) {
func setupRouter(t *testing.T) (*Router, func()) {
db, cleanTmpDb := setupTestNetworkDB(t)
client, _ := rpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, defaultNetworks, db)
client, _ := rpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, defaultNetworks, db, nil)
router := NewRouter(client, nil, nil, nil, nil, nil, nil, nil)

View File

@ -113,7 +113,11 @@ func NewService(
transferController.Start()
cryptoCompare := cryptocompare.NewClient()
coingecko := coingecko.NewClient()
cryptoCompareProxy := cryptocompare.NewClientWithURL(cryptocompare.CryptoCompareStatusProxyURL)
cryptoCompareProxy := cryptocompare.NewClientWithParams(cryptocompare.Params{
URL: cryptocompare.CryptoCompareStatusProxyURL,
User: config.WalletConfig.StatusProxyMarketUser,
Password: config.WalletConfig.StatusProxyMarketPassword,
})
marketManager := market.NewManager([]thirdparty.MarketDataProvider{cryptoCompare, coingecko, cryptoCompareProxy}, feed)
reader := NewReader(tokenManager, marketManager, token.NewPersistence(db), feed)
history := history.NewService(db, accountsDB, accountFeed, feed, rpcClient, tokenManager, marketManager, balanceCacher.Cache())

View File

@ -172,7 +172,7 @@ func (c *Client) getTokens() (map[string][]GeckoToken, error) {
params.Add("include_platform", "true")
url := c.tokensURL
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, nil)
if err != nil {
return nil, err
}
@ -216,7 +216,7 @@ func (c *Client) FetchPrices(symbols []string, currencies []string) (map[string]
params.Add("vs_currencies", strings.Join(currencies, ","))
url := fmt.Sprintf("%ssimple/price", baseURL)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, nil)
if err != nil {
return nil, err
}
@ -281,7 +281,7 @@ func (c *Client) FetchTokenMarketValues(symbols []string, currency string) (map[
params.Add("price_change_percentage", "1h,24h")
url := fmt.Sprintf("%scoins/markets", baseURL)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, nil)
if err != nil {
return nil, err
}
@ -343,7 +343,7 @@ func (c *Client) FetchHistoricalDailyPrices(symbol string, currency string, limi
params.Add("days", "30")
url := fmt.Sprintf("%scoins/%s/market_chart", baseURL, id)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, nil)
if err != nil {
return nil, err
}

View File

@ -7,13 +7,15 @@ import (
"net/url"
"strings"
"github.com/status-im/status-go/buildinfo"
"github.com/status-im/status-go/services/wallet/thirdparty"
"github.com/status-im/status-go/services/wallet/thirdparty/utils"
)
const baseURL = "https://min-api.cryptocompare.com"
const CryptoCompareStatusProxyURL = "https://cryptocompare.test.api.status.im"
const extraParamStatus = "Status.im"
const baseURL = "https://min-api.cryptocompare.com"
var CryptoCompareStatusProxyURL = fmt.Sprintf("https://%s.api.status.im/cryptocompare/", buildinfo.ApiProxyStageName)
type HistoricalPricesContainer struct {
Aggregated bool `json:"Aggregated"`
@ -34,9 +36,16 @@ type MarketValuesContainer struct {
Raw map[string]map[string]thirdparty.TokenMarketValues `json:"Raw"`
}
type Params struct {
URL string
User string
Password string
}
type Client struct {
httpClient *thirdparty.HTTPClient
baseURL string
creds *thirdparty.BasicCreds
}
func NewClient() *Client {
@ -46,10 +55,19 @@ func NewClient() *Client {
}
}
func NewClientWithURL(url string) *Client {
func NewClientWithParams(params Params) *Client {
var creds *thirdparty.BasicCreds
if params.User != "" {
creds = &thirdparty.BasicCreds{
User: params.User,
Password: params.Password,
}
}
return &Client{
httpClient: thirdparty.NewHTTPClient(),
baseURL: url,
baseURL: params.URL,
creds: creds,
}
}
@ -66,7 +84,7 @@ func (c *Client) FetchPrices(symbols []string, currencies []string) (map[string]
params.Add("extraParams", extraParamStatus)
url := fmt.Sprintf("%s/data/pricemulti", c.baseURL)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds)
if err != nil {
return nil, err
}
@ -89,7 +107,7 @@ func (c *Client) FetchPrices(symbols []string, currencies []string) (map[string]
func (c *Client) FetchTokenDetails(symbols []string) (map[string]thirdparty.TokenDetails, error) {
url := fmt.Sprintf("%s/data/all/coinlist", c.baseURL)
response, err := c.httpClient.DoGetRequest(context.Background(), url, nil)
response, err := c.httpClient.DoGetRequest(context.Background(), url, nil, c.creds)
if err != nil {
return nil, err
}
@ -122,7 +140,7 @@ func (c *Client) FetchTokenMarketValues(symbols []string, currency string) (map[
params.Add("extraParams", extraParamStatus)
url := fmt.Sprintf("%s/data/pricemultifull", c.baseURL)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds)
if err != nil {
return nil, err
}
@ -155,7 +173,7 @@ func (c *Client) FetchHistoricalHourlyPrices(symbol string, currency string, lim
params.Add("extraParams", extraParamStatus)
url := fmt.Sprintf("%s/data/v2/histohour", c.baseURL)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds)
if err != nil {
return item, err
}
@ -183,7 +201,7 @@ func (c *Client) FetchHistoricalDailyPrices(symbol string, currency string, limi
params.Add("extraParams", extraParamStatus)
url := fmt.Sprintf("%s/data/v2/histoday", c.baseURL)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params)
response, err := c.httpClient.DoGetRequest(context.Background(), url, params, c.creds)
if err != nil {
return item, err
}

View File

@ -13,6 +13,11 @@ import (
const requestTimeout = 5 * time.Second
const maxNumOfRequestRetries = 5
type BasicCreds struct {
User string
Password string
}
type HTTPClient struct {
client *http.Client
}
@ -25,7 +30,7 @@ func NewHTTPClient() *HTTPClient {
}
}
func (c *HTTPClient) DoGetRequest(ctx context.Context, url string, params netUrl.Values) ([]byte, error) {
func (c *HTTPClient) DoGetRequest(ctx context.Context, url string, params netUrl.Values, creds *BasicCreds) ([]byte, error) {
if len(params) > 0 {
url = url + "?" + params.Encode()
}
@ -35,6 +40,10 @@ func (c *HTTPClient) DoGetRequest(ctx context.Context, url string, params netUrl
return nil, err
}
if creds != nil {
req.SetBasicAuth(creds.User, creds.Password)
}
var resp *http.Response
for i := 0; i < maxNumOfRequestRetries; i++ {
resp, err = c.client.Do(req)
@ -56,7 +65,7 @@ func (c *HTTPClient) DoGetRequest(ctx context.Context, url string, params netUrl
return body, nil
}
func (c *HTTPClient) DoPostRequest(ctx context.Context, url string, params map[string]interface{}) ([]byte, error) {
func (c *HTTPClient) DoPostRequest(ctx context.Context, url string, params map[string]interface{}, creds *BasicCreds) ([]byte, error) {
jsonData, err := json.Marshal(params)
if err != nil {
return nil, err
@ -67,6 +76,10 @@ func (c *HTTPClient) DoPostRequest(ctx context.Context, url string, params map[s
return nil, err
}
if creds != nil {
req.SetBasicAuth(creds.User, creds.Password)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0")

View File

@ -0,0 +1,59 @@
package thirdparty
import (
"context"
"encoding/base64"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/stretchr/testify/require"
)
func TestHTTPClient_DoGetRequest(t *testing.T) {
// Create a new HTTPClient
client := NewHTTPClient()
expectedResponse := []byte("test response")
// Create a mock server
server := createMockServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "GET", r.Method)
require.Equal(t, "/test", r.URL.Path)
require.Equal(t, "value1", r.URL.Query().Get("param1"))
require.Equal(t, "value2", r.URL.Query().Get("param2"))
authToken := base64.StdEncoding.EncodeToString([]byte("username:password"))
require.Equal(t, fmt.Sprintf("Basic %s", authToken), r.Header.Get("Authorization"))
// Set the response headers
w.Header().Set("Content-Type", "application/json")
// Set the response body
_, _ = w.Write(expectedResponse)
}))
defer server.Close()
// Set up test data
expectedURL := server.URL + "/test"
expectedParams := url.Values{}
expectedParams.Set("param1", "value1")
expectedParams.Set("param2", "value2")
expectedCreds := &BasicCreds{
User: "username",
Password: "password",
}
// Make the GET request
ctx := context.Background()
response, err := client.DoGetRequest(ctx, expectedURL, expectedParams, expectedCreds)
// Verify the request
require.NoError(t, err)
require.Equal(t, expectedResponse, response)
}
func createMockServer(handler http.HandlerFunc) *httptest.Server {
return httptest.NewServer(handler)
}

View File

@ -56,7 +56,7 @@ func (c *ClientV5) BuildTransaction(ctx context.Context, srcTokenAddress common.
}
url := fmt.Sprintf(transactionsURL, c.chainID)
response, err := c.httpClient.DoPostRequest(ctx, url, params)
response, err := c.httpClient.DoPostRequest(ctx, url, params, nil)
if err != nil {
return Transaction{}, err
}

View File

@ -51,7 +51,7 @@ func (c *ClientV5) FetchPriceRoute(ctx context.Context, srcTokenAddress common.A
params.Add("excludeDEXS", "AugustusRFQ") // This DEX causes issues when creating the transaction
url := pricesURL
response, err := c.httpClient.DoGetRequest(ctx, url, params)
response, err := c.httpClient.DoGetRequest(ctx, url, params, nil)
if err != nil {
return Route{}, err
}

View File

@ -24,7 +24,7 @@ type TokensResponse struct {
func (c *ClientV5) FetchTokensList(ctx context.Context) ([]Token, error) {
url := fmt.Sprintf(tokensURL, c.chainID)
response, err := c.httpClient.DoGetRequest(ctx, url, nil)
response, err := c.httpClient.DoGetRequest(ctx, url, nil, nil)
if err != nil {
return nil, err
}

View File

@ -331,7 +331,7 @@ func Test_removeTokenBalanceOnEventAccountRemoved(t *testing.T) {
txServiceMockCtrl := gomock.NewController(t)
server, _ := fake.NewTestServer(txServiceMockCtrl)
client := gethrpc.DialInProc(server)
rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, appDB)
rpcClient, _ := rpc.NewClient(client, chainID, params.UpstreamRPCConfig{}, nil, appDB, nil)
rpcClient.UpstreamChainID = chainID
nm := network.NewManager(appDB)
mediaServer, err := mediaserver.NewMediaServer(appDB, nil, nil, walletDB)

View File

@ -1076,7 +1076,7 @@ func setupFindBlocksCommand(t *testing.T, accountAddress common.Address, fromBlo
return nil
}
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
client.SetClient(tc.NetworkID(), tc)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer, nil, nil, nil, token.NewPersistence(db))
tokenManager.SetTokens([]*token.Token{
@ -1339,7 +1339,7 @@ func TestFetchTransfersForLoadedBlocks(t *testing.T) {
currentBlock: 100,
}
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
client.SetClient(tc.NetworkID(), tc)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer, nil, nil, nil, token.NewPersistence(db))
@ -1463,7 +1463,7 @@ func TestFetchNewBlocksCommand_findBlocksWithEthTransfers(t *testing.T) {
currentBlock: 100,
}
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
client.SetClient(tc.NetworkID(), tc)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer, nil, nil, nil, token.NewPersistence(db))
@ -1543,7 +1543,7 @@ func TestFetchNewBlocksCommand_nonceDetection(t *testing.T) {
mediaServer, err := server.NewMediaServer(appdb, nil, nil, db)
require.NoError(t, err)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
client.SetClient(tc.NetworkID(), tc)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer, nil, nil, nil, token.NewPersistence(db))
@ -1657,7 +1657,7 @@ func TestFetchNewBlocksCommand(t *testing.T) {
}
//tc.printPreparedData = true
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
client.SetClient(tc.NetworkID(), tc)
tokenManager := token.NewTokenManager(db, client, community.NewManager(appdb, nil, nil), network.NewManager(appdb), appdb, mediaServer, nil, nil, nil, token.NewPersistence(db))
@ -1796,7 +1796,7 @@ func TestLoadBlocksAndTransfersCommand_FiniteFinishedInfiniteRunning(t *testing.
db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
require.NoError(t, err)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db)
client, _ := statusRpc.NewClient(nil, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
maker, _ := contracts.NewContractMaker(client)
wdb := NewDB(db)

View File

@ -45,7 +45,7 @@ func setupTestAPI(t *testing.T) (*API, func()) {
server, _ := fake.NewTestServer(txServiceMockCtrl)
client := gethrpc.DialInProc(server)
rpcClient, err := statusRPC.NewClient(client, 1, upstreamConfig, nil, db)
rpcClient, err := statusRPC.NewClient(client, 1, upstreamConfig, nil, db, nil)
require.NoError(t, err)
// import account keys

View File

@ -55,7 +55,7 @@ func (s *TransactorSuite) SetupTest() {
chainID := gethparams.AllEthashProtocolChanges.ChainID.Uint64()
db, err := sqlite.OpenUnecryptedDB(sqlite.InMemoryPath) // dummy to make rpc.Client happy
s.Require().NoError(err)
rpcClient, _ := rpc.NewClient(s.client, chainID, params.UpstreamRPCConfig{}, nil, db)
rpcClient, _ := rpc.NewClient(s.client, chainID, params.UpstreamRPCConfig{}, nil, db, nil)
rpcClient.UpstreamChainID = chainID
nodeConfig, err := utils.MakeTestNodeConfigWithDataDir("", "/tmp", chainID)
s.Require().NoError(err)