github.com/status-im/status-go@v1.1.0/services/connector/api.go (about)

     1  package connector
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/status-im/status-go/services/connector/commands"
     9  	persistence "github.com/status-im/status-go/services/connector/database"
    10  )
    11  
    12  var (
    13  	ErrInvalidResponseFromForwardedRpc = errors.New("invalid response from forwarded RPC")
    14  )
    15  
    16  type API struct {
    17  	s *Service
    18  	r *CommandRegistry
    19  	c *commands.ClientSideHandler
    20  }
    21  
    22  func NewAPI(s *Service) *API {
    23  	r := NewCommandRegistry()
    24  	c := commands.NewClientSideHandler()
    25  
    26  	// Transactions and signing
    27  	r.Register("eth_sendTransaction", &commands.SendTransactionCommand{
    28  		Db:            s.db,
    29  		ClientHandler: c,
    30  	})
    31  	r.Register("personal_sign", &commands.PersonalSignCommand{
    32  		Db:            s.db,
    33  		ClientHandler: c,
    34  	})
    35  
    36  	// Accounts query and dapp permissions
    37  	// NOTE: Some dApps expect same behavior for both eth_accounts and eth_requestAccounts
    38  	accountsCommand := &commands.RequestAccountsCommand{
    39  		ClientHandler: c,
    40  		Db:            s.db,
    41  	}
    42  	r.Register("eth_accounts", accountsCommand)
    43  	r.Register("eth_requestAccounts", accountsCommand)
    44  
    45  	// Active chain per dapp management
    46  	r.Register("eth_chainId", &commands.ChainIDCommand{
    47  		Db:             s.db,
    48  		NetworkManager: s.nm,
    49  	})
    50  	r.Register("wallet_switchEthereumChain", &commands.SwitchEthereumChainCommand{
    51  		Db:             s.db,
    52  		NetworkManager: s.nm,
    53  	})
    54  
    55  	// Permissions
    56  	r.Register("wallet_requestPermissions", &commands.RequestPermissionsCommand{})
    57  	r.Register("wallet_revokePermissions", &commands.RevokePermissionsCommand{
    58  		Db: s.db,
    59  	})
    60  
    61  	return &API{
    62  		s: s,
    63  		r: r,
    64  		c: c,
    65  	}
    66  }
    67  
    68  func (api *API) forwardRPC(URL string, inputJSON string) (interface{}, error) {
    69  	dApp, err := persistence.SelectDAppByUrl(api.s.db, URL)
    70  	if err != nil {
    71  		return "", err
    72  	}
    73  
    74  	if dApp == nil {
    75  		return "", commands.ErrDAppIsNotPermittedByUser
    76  	}
    77  
    78  	var response map[string]interface{}
    79  	rawResponse := api.s.rpc.CallRaw(inputJSON)
    80  	if err := json.Unmarshal([]byte(rawResponse), &response); err != nil {
    81  		return "", err
    82  	}
    83  
    84  	if errorField, ok := response["error"]; ok {
    85  		errorMap, _ := errorField.(map[string]interface{})
    86  		errorCode, _ := errorMap["code"].(float64)
    87  		errorMessage, _ := errorMap["message"].(string)
    88  		return nil, fmt.Errorf("error code %v: %s", errorCode, errorMessage)
    89  	}
    90  
    91  	if result, ok := response["result"]; ok {
    92  		return result, nil
    93  	}
    94  
    95  	return nil, ErrInvalidResponseFromForwardedRpc
    96  }
    97  
    98  func (api *API) CallRPC(inputJSON string) (interface{}, error) {
    99  	request, err := commands.RPCRequestFromJSON(inputJSON)
   100  	if err != nil {
   101  		return "", err
   102  	}
   103  
   104  	if command, exists := api.r.GetCommand(request.Method); exists {
   105  		return command.Execute(request)
   106  	}
   107  
   108  	return api.forwardRPC(request.URL, inputJSON)
   109  }
   110  
   111  func (api *API) RecallDAppPermission(origin string) error {
   112  	// TODO: close the websocket connection
   113  	return persistence.DeleteDApp(api.s.db, origin)
   114  }
   115  
   116  func (api *API) GetPermittedDAppsList() ([]persistence.DApp, error) {
   117  	return persistence.SelectAllDApps(api.s.db)
   118  }
   119  
   120  func (api *API) RequestAccountsAccepted(args commands.RequestAccountsAcceptedArgs) error {
   121  	return api.c.RequestAccountsAccepted(args)
   122  }
   123  
   124  func (api *API) RequestAccountsRejected(args commands.RejectedArgs) error {
   125  	return api.c.RequestAccountsRejected(args)
   126  }
   127  
   128  func (api *API) SendTransactionAccepted(args commands.SendTransactionAcceptedArgs) error {
   129  	return api.c.SendTransactionAccepted(args)
   130  }
   131  
   132  func (api *API) SendTransactionRejected(args commands.RejectedArgs) error {
   133  	return api.c.SendTransactionRejected(args)
   134  }
   135  
   136  func (api *API) PersonalSignAccepted(args commands.PersonalSignAcceptedArgs) error {
   137  	return api.c.PersonalSignAccepted(args)
   138  }
   139  
   140  func (api *API) PersonalSignRejected(args commands.RejectedArgs) error {
   141  	return api.c.PersonalSignRejected(args)
   142  }