github.com/status-im/status-go@v1.1.0/rpc/client_test.go (about)

     1  package rpc
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"encoding/base64"
     7  	"fmt"
     8  	"math/big"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"sync"
    12  	"testing"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/status-im/status-go/appdatabase"
    18  	"github.com/status-im/status-go/params"
    19  	"github.com/status-im/status-go/t/helpers"
    20  
    21  	"github.com/ethereum/go-ethereum/common"
    22  	gethrpc "github.com/ethereum/go-ethereum/rpc"
    23  )
    24  
    25  func setupTestNetworkDB(t *testing.T) (*sql.DB, func()) {
    26  	db, cleanup, err := helpers.SetupTestSQLDB(appdatabase.DbInitializer{}, "rpc-network-tests")
    27  	require.NoError(t, err)
    28  	return db, func() { require.NoError(t, cleanup()) }
    29  }
    30  
    31  func TestBlockedRoutesCall(t *testing.T) {
    32  	db, close := setupTestNetworkDB(t)
    33  	defer close()
    34  
    35  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    36  		fmt.Fprintln(w, `{
    37  			"id": 1,
    38  			"jsonrpc": "2.0",
    39  			"result": "0x234234e22b9ffc2387e18636e0534534a3d0c56b0243567432453264c16e78a2adc"
    40  		}`)
    41  	}))
    42  	defer ts.Close()
    43  
    44  	gethRPCClient, err := gethrpc.Dial(ts.URL)
    45  	require.NoError(t, err)
    46  
    47  	c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
    48  	require.NoError(t, err)
    49  
    50  	for _, m := range blockedMethods {
    51  		var (
    52  			result interface{}
    53  			err    error
    54  		)
    55  
    56  		err = c.Call(&result, 1, m)
    57  		require.EqualError(t, err, ErrMethodNotFound.Error())
    58  		require.Nil(t, result)
    59  
    60  		err = c.CallContext(context.Background(), &result, 1, m)
    61  		require.EqualError(t, err, ErrMethodNotFound.Error())
    62  		require.Nil(t, result)
    63  
    64  		err = c.CallContextIgnoringLocalHandlers(context.Background(), &result, 1, m)
    65  		require.EqualError(t, err, ErrMethodNotFound.Error())
    66  		require.Nil(t, result)
    67  	}
    68  }
    69  
    70  func TestBlockedRoutesRawCall(t *testing.T) {
    71  	db, close := setupTestNetworkDB(t)
    72  	defer close()
    73  
    74  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    75  		fmt.Fprintln(w, `{
    76  			"id": 1,
    77  			"jsonrpc": "2.0",
    78  			"result": "0x234234e22b9ffc2387e18636e0534534a3d0c56b0243567432453264c16e78a2adc"
    79  		}`)
    80  	}))
    81  	defer ts.Close()
    82  
    83  	gethRPCClient, err := gethrpc.Dial(ts.URL)
    84  	require.NoError(t, err)
    85  
    86  	c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: false, URL: ""}, []params.Network{}, db, nil)
    87  	require.NoError(t, err)
    88  
    89  	for _, m := range blockedMethods {
    90  		rawResult := c.CallRaw(fmt.Sprintf(`{
    91  			"jsonrpc": "2.0",
    92  			"id": 1,
    93  			"method": "%s",
    94  			"params": ["0xc862bf3cf4565d46abcbadaf4712a8940bfea729a91b9b0e338eab5166341ab5"]
    95  		}`, m))
    96  		require.Contains(t, rawResult, fmt.Sprintf(`{"code":-32700,"message":"%s"}`, ErrMethodNotFound))
    97  	}
    98  }
    99  
   100  func TestUpdateUpstreamURL(t *testing.T) {
   101  	db, close := setupTestNetworkDB(t)
   102  	defer close()
   103  
   104  	ts := createTestServer("")
   105  	defer ts.Close()
   106  
   107  	updatedUpstreamTs := createTestServer("")
   108  	defer updatedUpstreamTs.Close()
   109  
   110  	gethRPCClient, err := gethrpc.Dial(ts.URL)
   111  	require.NoError(t, err)
   112  
   113  	c, err := NewClient(gethRPCClient, 1, params.UpstreamRPCConfig{Enabled: true, URL: ts.URL}, []params.Network{}, db, nil)
   114  	require.NoError(t, err)
   115  	require.Equal(t, ts.URL, c.upstreamURL)
   116  
   117  	// cache the original upstream client
   118  	originalUpstreamClient := c.upstream
   119  
   120  	err = c.UpdateUpstreamURL(updatedUpstreamTs.URL)
   121  	require.NoError(t, err)
   122  	// the upstream cleint instance should change
   123  	require.NotEqual(t, originalUpstreamClient, c.upstream)
   124  	require.Equal(t, updatedUpstreamTs.URL, c.upstreamURL)
   125  }
   126  
   127  func createTestServer(resp string) *httptest.Server {
   128  	if resp == "" {
   129  		resp = `{
   130  			"id": 1,
   131  			"jsonrpc": "2.0",
   132  			"result": "0x234234e22b9ffc2387e18636e0534534a3d0c56b0243567432453264c16e78a2adc"
   133  		}`
   134  	}
   135  
   136  	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   137  		fmt.Fprintln(w, resp)
   138  	}))
   139  }
   140  
   141  func TestGetClientsUsingCache(t *testing.T) {
   142  	db, close := setupTestNetworkDB(t)
   143  	defer close()
   144  
   145  	providerConfig := params.ProviderConfig{
   146  		Enabled:  true,
   147  		Name:     ProviderStatusProxy,
   148  		User:     "user1",
   149  		Password: "pass1",
   150  	}
   151  	providerConfigs := []params.ProviderConfig{providerConfig}
   152  
   153  	var wg sync.WaitGroup
   154  	wg.Add(2) // 2 providers
   155  
   156  	// Create a new ServeMux
   157  	mux := http.NewServeMux()
   158  
   159  	path1 := "/foo"
   160  	path2 := "/bar"
   161  	// Register handlers for different URL paths
   162  	mux.HandleFunc(path1, func(w http.ResponseWriter, r *http.Request) {
   163  		authToken := base64.StdEncoding.EncodeToString([]byte(providerConfig.User + ":" + providerConfig.Password))
   164  		require.Equal(t, fmt.Sprintf("Basic %s", authToken), r.Header.Get("Authorization"))
   165  		wg.Done()
   166  	})
   167  
   168  	mux.HandleFunc(path2, func(w http.ResponseWriter, r *http.Request) {
   169  		authToken := base64.StdEncoding.EncodeToString([]byte(providerConfig.User + ":" + providerConfig.Password))
   170  		require.Equal(t, fmt.Sprintf("Basic %s", authToken), r.Header.Get("Authorization"))
   171  		wg.Done()
   172  	})
   173  
   174  	// Create a new server with the mux as the handler
   175  	server := httptest.NewServer(mux)
   176  	defer server.Close()
   177  
   178  	networks := []params.Network{
   179  		{
   180  			ChainID:            1,
   181  			DefaultRPCURL:      server.URL + path1,
   182  			DefaultFallbackURL: server.URL + path2,
   183  		},
   184  	}
   185  	c, err := NewClient(nil, 1, params.UpstreamRPCConfig{}, networks, db, providerConfigs)
   186  	require.NoError(t, err)
   187  
   188  	// Networks from DB must pick up DefaultRPCURL and DefaultFallbackURL
   189  	chainClient, err := c.getClientUsingCache(networks[0].ChainID)
   190  	require.NoError(t, err)
   191  	require.NotNil(t, chainClient)
   192  
   193  	// Make any call to provider. If test finishes, then all handlers were called and asserts inside them passed
   194  	balance, err := chainClient.BalanceAt(context.TODO(), common.Address{0x1}, big.NewInt(1))
   195  	assert.Error(t, err) // EOF, we dont return anything from the server, because of error iterate over all providers
   196  	assert.Nil(t, balance)
   197  	wg.Wait()
   198  }
   199  
   200  func TestUserAgent(t *testing.T) {
   201  	require.Equal(t, "procuratee-desktop/", rpcUserAgentName)
   202  	require.Equal(t, "procuratee-desktop-upstream/", rpcUserAgentUpstreamName)
   203  }