def test_serialize_camelCase(self): dict_request = JsonRpcRequest( "1", "methodname", { "param_name": "foo", "param2_name": "bar", "nested_param": { "nested_param_name": "baz" }, "normal_param": "qux" } ) dict_json = dict_request.to_json(Case.CAMEL) self.assertEqual("foo", dict_json["params"]["paramName"]) self.assertEqual("bar", dict_json["params"]["param2Name"]) self.assertEqual("baz", dict_json["params"]["nestedParam"]["nestedParamName"]) self.assertEqual("qux", dict_json["params"]["normalParam"]) list_request = JsonRpcRequest( "1", "methodname", ["1", "2", "3"] ) list_json = list_request.to_json(Case.CAMEL) self.assertEqual(["1", "2", "3"], list_json["params"]) str_request = JsonRpcRequest( "1", "methodname", "str_stuff", ) str_json = str_request.to_json(Case.CAMEL) self.assertEqual("strStuff", str_json["params"])
async def call(self, request: JsonRpcRequest) -> JsonRpcResponse: request_id = request.id assert request_id is not None await self.connected_event.wait() if not self.running: raise WsException( "Connection was broken when trying to call RPC method. " "Try reconnecting.") ws = self.ws assert ws is not None serialized_request = request.to_jsons() logger.trace("Sending message to websocket: {}", serialized_request) await ws.send(serialized_request) response = await self.get_rpc_response(request_id) if response is None: raise RpcTimedOut(None, "Please try again.") error = response.error if error: logger.error(log_messages.ETH_RPC_ERROR, error.message, error.data) raise error return response
async def call_rpc(self, method: str, params: Union[List[Any], Dict[Any, Any], None], request_id: Optional[str] = None) -> JsonRpcResponse: if request_id is None: request_id = str(self.current_request_id) self.current_request_id += 1 return await self.call(JsonRpcRequest(request_id, method, params))
async def producer(ws, _path): try: while True: message = await self.eth_ws_server_message_queue.get() await ws.send( JsonRpcRequest( None, "eth_subscription", {"subscription": self.eth_subscription_id, "result": message}, ).to_jsons() ) except Exception: # server closed, exit pass
async def test_disconnect_after_startup_retry(self): gateway_constants.WS_MIN_RECONNECT_TIMEOUT_S = 10 self.provider.retry_connection = True await self.provider.initialize() await self.provider.ws.close() await asyncio.sleep(0) self.assertTrue(self.provider.running) self.assertFalse(self.provider.connected_event.is_set()) rpc_message = JsonRpcResponse("1", "foo") await self.provider.get_test_websocket().recv_messages.put( rpc_message.to_jsons()) with self.assertRaises(WsException): await self.provider.get_rpc_response("1") send_task = asyncio.create_task( self.provider.call(JsonRpcRequest("2", "123", None))) await asyncio.sleep(0.1) self.assertFalse(send_task.done()) self.assertEqual(0, len(self.provider.get_test_websocket().send_messages)) # reconnect now await self.provider.connect() await asyncio.sleep(0) # re-emit new message await self.provider.get_test_websocket().recv_messages.put( rpc_message.to_jsons()) received_message = await self.provider.get_rpc_response("1") self.assertEqual(rpc_message, received_message) # still waiting for response self.assertFalse(send_task.done()) self.assertEqual(1, len(self.provider.get_test_websocket().send_messages)) # task finished response_rpc_message = JsonRpcResponse("2", "foo") await self.provider.get_test_websocket().recv_messages.put( response_rpc_message.to_jsons()) await asyncio.sleep(0.01) self.assertTrue(send_task.done()) self.assertEqual(response_rpc_message, send_task.result())
async def receive(self) -> None: # TODO: preferably this would be an infinite loop that waits on # self.connected_event.wait(), but it seems that `async for` never # throws an exception, even when the websocket gets disconnected. logger.trace("Started receiving on websocket.") ws = self.ws assert ws is not None async for next_message in ws: logger.trace("Received message on websocket: {}", next_message) # process response messages # noinspection PyBroadException try: response_message = JsonRpcResponse.from_jsons(next_message) # pylint: disable=broad-except except Exception: pass else: await self.response_messages.put(response_message) continue # process notification messages try: subscription_message = JsonRpcRequest.from_jsons(next_message) params = subscription_message.params assert isinstance(params, dict) await self.subscription_manager.receive_message( SubscriptionNotification( params["subscription"], params["result"], )) # pylint: disable=broad-except except Exception as e: logger.warning(log_messages.ETH_RPC_PROCESSING_ERROR, next_message, e, exc_info=True) logger.trace( "Temporarily stopped receiving message on websocket. Awaiting reconnection." )
async def consumer(ws, _path): try: async for message in ws: rpc_request = JsonRpcRequest.from_jsons(message) if rpc_request.method_name == "eth_subscribe": await ws.send( JsonRpcResponse(rpc_request.id, self.eth_subscription_id).to_jsons() ) elif rpc_request.method_name == "eth_getTransactionByHash": nonce = int(rpc_request.id) await ws.send( JsonRpcResponse( rpc_request.id, tx_to_eth_rpc_json(self.sample_transactions[nonce]) ).to_jsons() ) except Exception as e: # server closed, exit pass
def test_serialize_error_rpc_notification(self): rpc_notification = JsonRpcRequest(None, "sub", ["subid", {}]) with self.assertRaises(ValueError): JsonRpcResponse.from_json(rpc_notification.to_json())