diff --git a/api/api.go b/api/api.go index ced9f6cdf..55e1002e7 100644 --- a/api/api.go +++ b/api/api.go @@ -33,10 +33,13 @@ var ( ) //go:embed cadence/scripts/bridged_account_call.cdc -var bridgedAccountCall []byte +var BridgedAccountCall []byte //go:embed cadence/transactions/evm_run.cdc -var evmRunTx []byte +var EVMRunTx []byte + +//go:embed cadence/scripts/evm_address_balance.cdc +var EVMAddressBalance []byte func SupportedAPIs(blockChainAPI *BlockChainAPI) []rpc.API { return []rpc.API{ @@ -141,7 +144,7 @@ func (api *BlockChainAPI) SendRawTransaction( } tx := flow.NewTransaction(). - SetScript(evmRunTx). + SetScript(EVMRunTx). SetProposalKey(account.Address, accountKey.Index, accountKey.SequenceNumber). SetReferenceBlockID(block.ID). SetPayer(account.Address). @@ -228,7 +231,29 @@ func (s *BlockChainAPI) GetBalance( address common.Address, blockNumberOrHash *rpc.BlockNumberOrHash, ) (*hexutil.Big, error) { - return (*hexutil.Big)(big.NewInt(101)), nil + addressBytes := make([]cadence.Value, 0) + for _, bt := range address.Bytes() { + addressBytes = append(addressBytes, cadence.UInt8(bt)) + } + evmAddress := cadence.NewArray( + addressBytes, + ).WithType(cadence.NewConstantSizedArrayType(20, cadence.TheUInt8Type)) + + value, err := s.FlowClient.ExecuteScriptAtLatestBlock( + ctx, + EVMAddressBalance, + []cadence.Value{evmAddress}, + ) + if err != nil { + return nil, err + } + + balance, ok := value.(cadence.UFix64) + if !ok { + return nil, fmt.Errorf("script doesn't return UFix64 as it should") + } + + return (*hexutil.Big)(big.NewInt(int64(balance))), nil } // eth_getCode (returns the code for the given address) @@ -795,7 +820,7 @@ func (s *BlockChainAPI) Call( value, err := s.FlowClient.ExecuteScriptAtLatestBlock( ctx, - bridgedAccountCall, + BridgedAccountCall, []cadence.Value{encodedTx, encodedTo}, ) if err != nil { diff --git a/api/api_test.go b/api/api_test.go index 35ca246e8..bc9a858b9 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -198,6 +198,13 @@ func TestBlockChainAPI(t *testing.T) { }) t.Run("GetBalance", func(t *testing.T) { + mockFlowClient := new(mocks.MockAccessClient) + blockchainAPI = api.NewBlockChainAPI(config, store, mockFlowClient) + + result, err := cadence.NewUFix64("1500.0") + require.NoError(t, err) + mockFlowClient.On("ExecuteScriptAtLatestBlock", mock.Anything, mock.Anything, mock.Anything).Return(result, nil) + key, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(key.PublicKey) balance, err := blockchainAPI.GetBalance( @@ -207,7 +214,7 @@ func TestBlockChainAPI(t *testing.T) { ) require.NoError(t, err) - assert.Equal(t, balance, (*hexutil.Big)(big.NewInt(101))) + assert.Equal(t, balance, (*hexutil.Big)(big.NewInt(150000000000))) }) t.Run("GetProof", func(t *testing.T) { diff --git a/api/cadence/scripts/evm_address_balance.cdc b/api/cadence/scripts/evm_address_balance.cdc new file mode 100644 index 000000000..b715634cd --- /dev/null +++ b/api/cadence/scripts/evm_address_balance.cdc @@ -0,0 +1,8 @@ +import EVM from 0xf8d6e0586b0a20c7 + +access(all) +fun main(addressBytes: [UInt8; 20]): UFix64 { + let address = EVM.EVMAddress(bytes: addressBytes) + + return address.balance().flow +} diff --git a/api/fixtures/eth_json_rpc_requests.json b/api/fixtures/eth_json_rpc_requests.json index c85bec0d6..9f52f63af 100644 --- a/api/fixtures/eth_json_rpc_requests.json +++ b/api/fixtures/eth_json_rpc_requests.json @@ -2,7 +2,6 @@ {"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params": []} {"jsonrpc":"2.0","id":1,"method":"eth_syncing","params": []} {"jsonrpc":"2.0","id":1,"method":"eth_gasPrice","params":[]} -{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1","latest"]} {"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":["0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b","0x2"]} {"jsonrpc":"2.0","id":1,"method":"eth_getStorageAt","params":["0x295a70b2de5e3953354a6a8344e616ed314d7251","0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9","latest"]} {"jsonrpc":"2.0","id":1,"method":"eth_getTransactionCount","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1","latest"]} diff --git a/api/fixtures/eth_json_rpc_responses.json b/api/fixtures/eth_json_rpc_responses.json index dedab33b2..eae32095b 100644 --- a/api/fixtures/eth_json_rpc_responses.json +++ b/api/fixtures/eth_json_rpc_responses.json @@ -2,7 +2,6 @@ {"jsonrpc":"2.0","id":1,"result":"0x0"} {"jsonrpc":"2.0","id":1,"result":false} {"jsonrpc":"2.0","id":1,"result":"0x1dfd14000"} -{"jsonrpc":"2.0","id":1,"result":"0x65"} {"jsonrpc":"2.0","id":1,"result":"0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056"} {"jsonrpc":"2.0","id":1,"result":"0x600160008035811a818181146012578301005b601b6001356025565b8060005260206000f25b600060078202905091905056"} {"jsonrpc":"2.0","id":1,"result":"0x0"} diff --git a/api/server_test.go b/api/server_test.go index 8836ab160..ae0dd664b 100644 --- a/api/server_test.go +++ b/api/server_test.go @@ -136,7 +136,12 @@ func TestServerJSONRPCOveHTTPHandler(t *testing.T) { returnValue := cadence.NewArray( toBytes, ).WithType(cadence.NewVariableSizedArrayType(cadence.TheUInt8Type)) - mockFlowClient.On("ExecuteScriptAtLatestBlock", mock.Anything, mock.Anything, mock.Anything).Return(returnValue, nil) + mockFlowClient.On( + "ExecuteScriptAtLatestBlock", + mock.Anything, + api.BridgedAccountCall, + mock.Anything, + ).Once().Return(returnValue, nil) blockchainAPI = api.NewBlockChainAPI(config, store, mockFlowClient) @@ -223,6 +228,30 @@ func TestServerJSONRPCOveHTTPHandler(t *testing.T) { assert.Equal(t, expectedResponse, strings.TrimSuffix(string(content), "\n")) }) + + t.Run("eth_getBalance", func(t *testing.T) { + request := `{"jsonrpc":"2.0","id":1,"method":"eth_getBalance","params":["0x407d73d8a49eeb85d32cf465507dd71d507100c1","latest"]}` + expectedResponse := `{"jsonrpc":"2.0","id":1,"result":"0x22ecb25c00"}` + + result, err := cadence.NewUFix64("1500.0") + require.NoError(t, err) + mockFlowClient.On( + "ExecuteScriptAtLatestBlock", + mock.Anything, + api.EVMAddressBalance, + mock.Anything, + ).Once().Return(result, nil) + + resp := rpcRequest(url, request, "origin", "test.com") + defer resp.Body.Close() + + content, err := io.ReadAll(resp.Body) + if err != nil { + panic(err) + } + + assert.Equal(t, expectedResponse, strings.TrimSuffix(string(content), "\n")) + }) } func TestServerJSONRPCOveWebSocketHandler(t *testing.T) {