Skip to content

Commit

Permalink
Merge pull request #53 from m-Peter/add-net-and-web3-namespaces
Browse files Browse the repository at this point in the history
Add `net` and `web3` namespaces
  • Loading branch information
sideninja authored Feb 20, 2024
2 parents 810c84a + cead066 commit be37111
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 15 deletions.
14 changes: 13 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ import (
"github.com/onflow/flow-go-sdk/crypto"
)

const EthNamespace = "eth"
const (
EthNamespace = "eth"
Web3Namespace = "web3"
NetNamespace = "net"
)

// TODO: Fetch these from flow-go/fvm/evm/emulator/config.go
var (
Expand All @@ -45,6 +49,14 @@ func SupportedAPIs(blockChainAPI *BlockChainAPI) []rpc.API {
Namespace: EthNamespace,
Service: blockChainAPI,
},
{
Namespace: Web3Namespace,
Service: &Web3API{},
},
{
Namespace: NetNamespace,
Service: &NetAPI{},
},
}
}

Expand Down
26 changes: 26 additions & 0 deletions api/net_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package api

import (
"fmt"

"github.com/ethereum/go-ethereum/common/hexutil"
)

// NetAPI offers network related RPC methods
type NetAPI struct{}

// Listening returns an indication if the node is
// listening for network connections.
func (s *NetAPI) Listening() bool {
return true // always listening
}

// PeerCount returns the number of connected peers
func (s *NetAPI) PeerCount() hexutil.Uint {
return 1
}

// Version returns the current ethereum protocol version.
func (s *NetAPI) Version() string {
return fmt.Sprintf("%d", 666)
}
17 changes: 8 additions & 9 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type rpcHandler struct {
}

type httpServer struct {
log zerolog.Logger
logger zerolog.Logger
timeouts rpc.HTTPTimeouts

server *http.Server
Expand All @@ -46,9 +46,9 @@ const (
shutdownTimeout = 5 * time.Second
)

func NewHTTPServer(log zerolog.Logger, timeouts rpc.HTTPTimeouts) *httpServer {
func NewHTTPServer(logger zerolog.Logger, timeouts rpc.HTTPTimeouts) *httpServer {
return &httpServer{
log: log,
logger: logger,
timeouts: timeouts,
}
}
Expand Down Expand Up @@ -153,7 +153,7 @@ func (h *httpServer) Start() error {
// Initialize the server.
h.server = &http.Server{Handler: h}
if h.timeouts != (rpc.HTTPTimeouts{}) {
CheckTimeouts(h.log, &h.timeouts)
CheckTimeouts(h.logger, &h.timeouts)
h.server.ReadTimeout = h.timeouts.ReadTimeout
h.server.ReadHeaderTimeout = h.timeouts.ReadHeaderTimeout
h.server.WriteTimeout = h.timeouts.WriteTimeout
Expand All @@ -174,12 +174,11 @@ func (h *httpServer) Start() error {
go h.server.Serve(listener)

if h.rpcAllowed() {
log.Info().Msg(fmt.Sprintf("JSON-RPC over HTTP enabled: %v/rpc", listener.Addr()))
h.logger.Info().Msgf("JSON-RPC over HTTP enabled: %s", listener.Addr())
}

if h.wsAllowed() {
url := fmt.Sprintf("ws://%v/ws", listener.Addr())
log.Info().Msg(fmt.Sprint("JSON-RPC over WebSocket enabled: ", url))
h.logger.Info().Msgf("JSON-RPC over WebSocket enabled: %s", listener.Addr())
}

return nil
Expand All @@ -200,7 +199,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Check if WebSocket request and serve if JSON-RPC over WebSocket is enabled
ws := h.wsHandler
if ws != nil && isWebSocket(r) {
if checkPath(r, "/ws") {
if checkPath(r, "") {
ws.ServeHTTP(w, r)
return
}
Expand All @@ -209,7 +208,7 @@ func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// If JSON-RPC over HTTP is enabled, try to serve the request
rpc := h.httpHandler
if rpc != nil {
if checkPath(r, "/rpc") {
if checkPath(r, "") {
rpc.ServeHTTP(w, r)
return
}
Expand Down
62 changes: 57 additions & 5 deletions api/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"github.com/onflow/flow-evm-gateway/storage"
"github.com/onflow/flow-go-sdk"
"github.com/onflow/flow-go-sdk/access/grpc"
sdkCrypto "github.com/onflow/flow-go-sdk/crypto"
"github.com/onflow/flow-go-sdk/crypto"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
Expand Down Expand Up @@ -52,7 +52,7 @@ func TestServerJSONRPCOveHTTPHandler(t *testing.T) {
panic(err)
}

url := "http://" + srv.ListenAddr() + "/rpc"
url := "http://" + srv.ListenAddr()

expectedResponses := strings.Split(responses, "\n")
for i, request := range strings.Split(requests, "\n") {
Expand Down Expand Up @@ -181,13 +181,13 @@ func TestServerJSONRPCOveHTTPHandler(t *testing.T) {
}
mockFlowClient.On("GetLatestBlock", mock.Anything, mock.Anything).Return(block, nil)

privateKey, err := sdkCrypto.DecodePrivateKeyHex(sdkCrypto.ECDSA_P256, strings.Replace("2619878f0e2ff438d17835c2a4561cb87b4d24d72d12ec34569acd0dd4af7c21", "0x", "", 1))
privateKey, err := crypto.DecodePrivateKeyHex(crypto.ECDSA_P256, strings.Replace("2619878f0e2ff438d17835c2a4561cb87b4d24d72d12ec34569acd0dd4af7c21", "0x", "", 1))
require.NoError(t, err)
key := &flow.AccountKey{
Index: 0,
PublicKey: privateKey.PublicKey(),
SigAlgo: privateKey.Algorithm(),
HashAlgo: sdkCrypto.SHA3_256,
HashAlgo: crypto.SHA3_256,
Weight: 1000,
SequenceNumber: uint64(0),
Revoked: false,
Expand Down Expand Up @@ -486,6 +486,58 @@ func TestServerJSONRPCOveHTTPHandler(t *testing.T) {

assert.Equal(t, expectedResponse, strings.TrimSuffix(string(content), "\n"))
})

t.Run("net endpoints", func(t *testing.T) {
requests := `
[
{"jsonrpc":"2.0","id":1,"method":"net_listening","params":[]},
{"jsonrpc":"2.0","id":2,"method":"net_peerCount","params":[]},
{"jsonrpc":"2.0","id":3,"method":"net_version","params":[]}
]
`
expectedResponse := `
[
{"jsonrpc":"2.0","id":1,"result":true},
{"jsonrpc":"2.0","id":2,"result":"0x1"},
{"jsonrpc":"2.0","id":3,"result":"666"}
]
`

resp := rpcRequest(url, requests, "origin", "test.com")
defer resp.Body.Close()

content, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}

assert.JSONEq(t, expectedResponse, string(content))
})

t.Run("web3 endpoints", func(t *testing.T) {
requests := `
[
{"jsonrpc":"2.0","id":1,"method":"web3_clientVersion","params":[]},
{"jsonrpc":"2.0","id":2,"method":"web3_sha3","params":["0x68656c6c6f20776f726c64"]}
]
`
expectedResponse := `
[
{"jsonrpc":"2.0","id":1,"result":"[email protected]"},
{"jsonrpc":"2.0","id":2,"result":"0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"}
]
`

resp := rpcRequest(url, requests, "origin", "test.com")
defer resp.Body.Close()

content, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}

assert.JSONEq(t, expectedResponse, string(content))
})
}

func TestServerJSONRPCOveWebSocketHandler(t *testing.T) {
Expand All @@ -508,7 +560,7 @@ func TestServerJSONRPCOveWebSocketHandler(t *testing.T) {
panic(err)
}

url := "ws://" + srv.ListenAddr() + "/ws"
url := "ws://" + srv.ListenAddr()

extraHeaders := []string{"Origin", "*"}
headers := make(http.Header)
Expand Down
20 changes: 20 additions & 0 deletions api/web3_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package api

import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
)

// Web3API offers helper utils
type Web3API struct{}

// ClientVersion returns the node name
func (s *Web3API) ClientVersion() string {
return "[email protected]"
}

// Sha3 applies the ethereum sha3 implementation on the input.
// It assumes the input is hex encoded.
func (s *Web3API) Sha3(input hexutil.Bytes) hexutil.Bytes {
return crypto.Keccak256(input)
}

0 comments on commit be37111

Please sign in to comment.