def setUp(self) -> None: self._account_model = BdnAccountModelBase( account_id="", logical_account_name="", certificate="", expire_date=utils_constants.DEFAULT_EXPIRATION_DATE.isoformat(), cloud_api=BdnServiceModelConfigBase( msg_quota=None, permit=BdnServiceModelBase(service_type=BdnServiceType.PERMIT), expire_date=utils_constants.DEFAULT_EXPIRATION_DATE.isoformat( ), ), blockchain_protocol="Ethereum", blockchain_network="Mainnet", ) self.rpc_port = helpers.get_free_port() opts = gateway_helpers.get_gateway_opts( 8000, rpc_port=self.rpc_port, account_model=self._account_model, blockchain_protocol="Ethereum", ) self.node = MockGatewayNode(opts) self.node.eth_ws_proxy_publisher = MockEthWsProxyPublisher( None, None, None, self.node) self.node.eth_ws_proxy_publisher.call_rpc = AsyncMock( return_value=JsonRpcResponse(request_id=1)) self.sut = EthOnBlockFeed(self.node)
async def test_multiple_rpc_calls_mixed_response(self): # unlikely to ever actually happen in practice, but should be handled async with WsProvider(self.ws_uri) as ws: self.assertEqual(1, len(self.server._connections)) connection_handler = self.server._connections[0] connection_handler.rpc_handler.handle_request = AsyncMock() subscribe_task_1 = asyncio.create_task( ws.call_bx(RpcRequestType.SUBSCRIBE, ["newTxs"], request_id="123")) await asyncio.sleep(0) subscribe_task_2 = asyncio.create_task( ws.call_bx(RpcRequestType.SUBSCRIBE, ["newTxs"], request_id="124")) server_ws = connection_handler.ws assert server_ws is not None # send responses out of order await server_ws.send(JsonRpcResponse("124", "subid2").to_jsons()) await server_ws.send(JsonRpcResponse("123", "subid1").to_jsons()) await asyncio.sleep(0.01) self.assertTrue(subscribe_task_1.done()) self.assertTrue(subscribe_task_2.done()) subscription_1 = subscribe_task_1.result() self.assertEqual("123", subscription_1.id) self.assertEqual("subid1", subscription_1.result) subscription_2 = subscribe_task_2.result() self.assertEqual("subid2", subscription_2.result)
async def test_error_response(self): call_name = "test_eth_call_1" subscriber = self.sut.subscribe( {"call_params": [{ "data": hex(1), "name": call_name }]}) self.node.eth_ws_proxy_publisher.call_rpc = AsyncMock( side_effect=RpcError(RpcErrorCode.SERVER_ERROR, "1", None, "out of gas")) # test ethNode Error response # the error will be sent to the subscriber # the specific call will be disabled and a notification will be sent to the subscriber await self._publish_to_feed(1) self.assertEqual(subscriber.messages.qsize(), 3) expected_response_names = { call_name, str(EventType.TASK_COMPLETED_EVENT), str(EventType.TASK_DISABLED_EVENT), } for msg in _iter_queue(subscriber.messages): self.assertIn(msg["name"], expected_response_names) expected_response_names.discard(msg["name"]) self.assertFalse(expected_response_names) # expect only TaskCompleted response when the subscribed calls are disabled await self._publish_to_feed(2) self.assertEqual(subscriber.messages.qsize(), 1)
async def test_compare_tx_feeds_script_new_txs(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed( EthNewTransactionFeed() ) sys.argv = [ "main.py", "--gateway", "ws://127.0.0.1:8005", "--eth", "ws://123.4.5.6:7890", "--feed-name", "newTxs", "--min-gas-price", "0.000000001", "--num-intervals", "1", "--interval", "2", "--lead-time", "0", "--trail-time", "0", "--ignore-delta", "5", "--addresses", "0xef26fd0f0f95d28408fc663b1e4de25855ff7f73" ] compare_tx_feeds.process_new_txs_eth = AsyncMock() asyncio.create_task(self.send_tx_to_new_txs_feed()) try: await compare_tx_feeds.main() except SystemExit: print("Script exited normally.")
async def test_onblock_feed_default_subscribe(self): self.gateway_node.opts.eth_ws_uri = f"ws://{constants.LOCALHOST}:8005" block_height = 100 name = "abc123" self.gateway_node.feed_manager.register_feed( EthOnBlockFeed(self.gateway_node)) self.gateway_node.eth_ws_proxy_publisher = MockEthWsProxyPublisher( "", None, None, self.gateway_node) self.gateway_node.eth_ws_proxy_publisher.call_rpc = AsyncMock( return_value=JsonRpcResponse(request_id=1)) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( rpc_constants.ETH_ON_BLOCK_FEED_NAME, {"call_params": [{ "data": "0x", "name": name }]}, ) self.gateway_node.feed_manager.publish_to_feed( FeedKey(rpc_constants.ETH_ON_BLOCK_FEED_NAME), EventNotification(block_height=block_height), ) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) print(subscription_message) self.assertEqual(block_height, subscription_message.notification["blockHeight"]) self.assertEqual(name, subscription_message.notification["name"])
async def test_connection_and_close_unexpectedly(self): async with WsProvider(self.ws_uri) as ws: self.assertEqual(1, len(self.server._connections)) connection_handler = self.server._connections[0] connection_handler.rpc_handler.handle_request = AsyncMock( side_effect=connection_handler.close) with self.assertRaises(WsException): await ws.subscribe("newTxs")
async def test_eth_transaction_receipts_feed_specify_include(self): self.gateway_node.opts.eth_ws_uri = f"ws://{constants.LOCALHOST}:8005" self.gateway_node.feed_manager.register_feed( EthTransactionReceiptsFeed(self.gateway_node, 0)) self.gateway_node.eth_ws_proxy_publisher = MockEthWsProxyPublisher( "", None, None, self.gateway_node) receipt_response = { "blockHash": "0xe6f67c6948158c45dct10b169ad6bf3a96c6402489733a03051feaf7d09e7b54", "blockNumber": "0xaf25e5", "cumulativeGasUsed": "0xbdb9ae", "from": "0x82170dd1cec50107963bf1ba1e80955ea302c5ce", "gasUsed": "0x5208", "logs": [], "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "status": "0x1", "to": "0xa09f63d9a0b0fbe89e41e51282ad660e7c876165", "transactionHash": "0xbcdc5b22bf463f9b8766dd61cc133caf13472b6ae8474061134d9dc2983625f6", "transactionIndex": "0x90" } receipt_result = { "transactionHash": "0xbcdc5b22bf463f9b8766dd61cc133caf13472b6ae8474061134d9dc2983625f6" } self.gateway_node.eth_ws_proxy_publisher.call_rpc = AsyncMock( return_value=JsonRpcResponse(request_id=1, result=receipt_response)) block = mock_eth_messages.get_dummy_block(5) internal_block_info = InternalEthBlockInfo.from_new_block_msg( NewBlockEthProtocolMessage(None, block, 1)) eth_raw_block = EthRawBlock( 1, internal_block_info.block_hash(), FeedSource.BLOCKCHAIN_RPC, get_block_message_lazy(internal_block_info)) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( rpc_constants.ETH_TRANSACTION_RECEIPTS_FEED_NAME, {"include": ["receipt.transaction_hash"]}) self.gateway_node.feed_manager.publish_to_feed( FeedKey(rpc_constants.ETH_TRANSACTION_RECEIPTS_FEED_NAME), eth_raw_block) for i in range(len(block.transactions)): subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(subscription_message.notification, {"receipt": receipt_result})
async def test_blxr_eth_call(self): self.gateway_node.eth_ws_proxy_publisher = MockEthWsProxyPublisher( None, None, None, None) self.gateway_node.eth_ws_proxy_publisher.call_rpc = AsyncMock( return_value=JsonRpcResponse(request_id=1)) result = await self.request( BxJsonRpcRequest( "1", RpcRequestType.BLXR_ETH_CALL, { rpc_constants.TRANSACTION_JSON_PARAMS_KEY: TRANSACTION_JSON, rpc_constants.TAG_PARAMS_KEY: "latest" })) self.gateway_node.eth_ws_proxy_publisher.call_rpc.mock.assert_called_with( "eth_call", [TRANSACTION_JSON, "latest"]) self.assertIsNone(result.error)
async def test_compare_tx_feeds_script_new_txs_not_include_from_blockchain(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed( EthNewTransactionFeed() ) sys.argv = [ "main.py", "--gateway", "ws://127.0.0.1:8005", "--num-intervals", "1", "--interval", "2", "--lead-time", "0", "--trail-time", "0", ] compare_tx_feeds.process_new_txs_eth = AsyncMock() asyncio.create_task(self.send_tx_to_new_txs_feed(FeedSource.BLOCKCHAIN_SOCKET)) try: await compare_tx_feeds.main() except SystemExit: pass
async def test_compare_tx_feeds_script_pending_txs(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue) ) sys.argv = [ "main.py", "--gateway", "ws://127.0.0.1:8005", "--eth", "ws://123.4.5.6:7890", "--feed-name", "pendingTxs", "--num-intervals", "1", "--interval", "2", "--lead-time", "0", "--trail-time", "0", ] compare_tx_feeds.process_new_txs_eth = AsyncMock() asyncio.create_task(self.send_tx_to_pending_txs_feed()) try: await compare_tx_feeds.main() except SystemExit: print("Script exited normally.")