From a27d511b5cdd3e0075095a373340df1e374a9a8a Mon Sep 17 00:00:00 2001 From: monty-sei Date: Mon, 12 Jan 2026 21:48:00 +1100 Subject: [PATCH] Adjusted RPC http requests to use POST instead of GET (#2675) RPC calls for the EVM CLI were attempting to send methods via GET instead of POST, resulting in failed extraction of results from the associated RPC calls as none were being returned. Adjustments to `getChainId()`, `getNonce()` and `CmdAssociateAddress()` were made NOTE: the latter `CmdAssociateAddress` had an internal cmd method call to `sei_associate` using GET instead of POST. Fixes REL-107 (cherry picked from commit 7c036d1372103810f76e6e603c4a4f0a82e1d99a) --- x/evm/client/cli/tx.go | 6 +-- x/evm/client/cli/tx_test.go | 105 ++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 x/evm/client/cli/tx_test.go diff --git a/x/evm/client/cli/tx.go b/x/evm/client/cli/tx.go index d6f183c135..0852a0c642 100644 --- a/x/evm/client/cli/tx.go +++ b/x/evm/client/cli/tx.go @@ -134,7 +134,7 @@ func CmdAssociateAddress() *cobra.Command { if err != nil { return err } - req, err := http.NewRequest(http.MethodGet, rpc, strings.NewReader(body)) + req, err := http.NewRequest(http.MethodPost, rpc, strings.NewReader(body)) if err != nil { return err } @@ -607,7 +607,7 @@ func getPrivateKey(cmd *cobra.Command) (*ecdsa.PrivateKey, error) { func getNonce(rpc string, key ecdsa.PublicKey) (uint64, error) { nonceQuery := fmt.Sprintf("{\"jsonrpc\": \"2.0\",\"method\": \"eth_getTransactionCount\",\"params\":[\"%s\",\"pending\"],\"id\":\"send-cli\"}", crypto.PubkeyToAddress(key).Hex()) - req, err := http.NewRequest(http.MethodGet, rpc, strings.NewReader(nonceQuery)) + req, err := http.NewRequest(http.MethodPost, rpc, strings.NewReader(nonceQuery)) if err != nil { return 0, err } @@ -634,7 +634,7 @@ func getNonce(rpc string, key ecdsa.PublicKey) (uint64, error) { func getChainId(rpc string) (*big.Int, error) { q := "{\"jsonrpc\": \"2.0\",\"method\": \"eth_chainId\",\"params\":[],\"id\":\"send-cli\"}" - req, err := http.NewRequest(http.MethodGet, rpc, strings.NewReader(q)) + req, err := http.NewRequest(http.MethodPost, rpc, strings.NewReader(q)) if err != nil { return nil, err } diff --git a/x/evm/client/cli/tx_test.go b/x/evm/client/cli/tx_test.go new file mode 100644 index 0000000000..31812c099e --- /dev/null +++ b/x/evm/client/cli/tx_test.go @@ -0,0 +1,105 @@ +package cli + +import ( + "crypto/ecdsa" + "crypto/rand" + "encoding/json" + "math/big" + "net/http" + "net/http/httptest" + "testing" + + "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" +) + +func TestGetChainId(t *testing.T) { + + tests := []struct { + name string + chainIdHex string + chainId int64 + hasURL bool + }{ + {"mainnet chain id", "0x531", 1329, true}, + {"testnet chain id", "0x530", 1328, true}, + {"url error chain id", "", 0, false}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + + //Setup RPC Server with result and get URL + rpcServer := getRPCServer(t, test.chainIdHex) + defer rpcServer.Close() + + if test.hasURL { + chainId, err := getChainId(rpcServer.URL) + require.NoError(t, err) + require.Equal(t, *big.NewInt(test.chainId), *chainId) + } else { + _, err := getChainId("") + require.Error(t, err) + } + }) + } +} + +func TestGetNonce(t *testing.T) { + //Test nonce is zero for a new wallet + //Generate a new privateKey from secp256k1 and get public key + privateKey, err := ecdsa.GenerateKey(crypto.S256(), rand.Reader) + require.NoError(t, err) + + tests := []struct { + name string + publicKey ecdsa.PublicKey + nonceHex string + nonce uint64 + }{ + {"new address", privateKey.PublicKey, "0x0", uint64(0)}, + {"active address", privateKey.PublicKey, "0x5", uint64(5)}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + + //Setup RPC Server with result and get URL + rpcServer := getRPCServer(t, test.nonceHex) + defer rpcServer.Close() + + nonce, err := getNonce(rpcServer.URL, test.publicKey) + require.NoError(t, err) + require.Equal(t, nonce, test.nonce) + }) + } +} + +func getRPCServer(t *testing.T, result string) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + + //Standard method call response from POST request to RPC + response := map[string]any{ + "jsonrpc": "2.0", + "id": "send-cli", + "result": result, + } + + //Adjust to default GET response if not POST + if r.Method != http.MethodPost { + response = map[string]any{ + "sei": []map[string]any{ + { + "id": "evm:local", + "alias": "sei", + "state": "OK", + }, + }, + } + } + + w.Header().Set("Content-Type", "application/json") + err := json.NewEncoder(w).Encode(response) + require.NoError(t, err) + })) +}