async def test_connection_and_close_while_receiving_subscriptions(self): async with WsProvider(self.ws_uri) as ws: self.assertEqual(1, len(self.server._connections)) connection_handler = self.server._connections[0] self.assertTrue(ws.running) subscription_id = await ws.subscribe("newTxs") tx_contents = helpers.generate_bytes(250) raw_published_message = RawTransaction( helpers.generate_object_hash(), memoryview(tx_contents)) serialized_published_message = RawTransactionFeedEntry( raw_published_message.tx_hash, raw_published_message.tx_contents) self.gateway_node.feed_manager.publish_to_feed( "newTxs", raw_published_message) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(serialized_published_message.tx_hash, subscription_message.notification["tx_hash"]) self.assertEqual(serialized_published_message.tx_contents, subscription_message.notification["tx_contents"]) task = asyncio.create_task( ws.get_next_subscription_notification_by_id(subscription_id)) await connection_handler.close() await asyncio.sleep(0.01) exception = task.exception() self.assertIsInstance(exception, WsException)
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_eth_pending_tx_feed_subscribe_handles_no_duplicates(self): self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue)) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET, local_region=True) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe("pendingTxs", {"duplicates": False}) self.gateway_node.feed_manager.publish_to_feed( FeedKey("pendingTxs"), eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) # will not publish twice self.gateway_node.feed_manager.publish_to_feed( FeedKey("pendingTxs"), eth_transaction) with self.assertRaises(asyncio.TimeoutError): await asyncio.wait_for( ws.get_next_subscription_notification_by_id( subscription_id), 0.1)
async def test_eth_new_transactions_feed_subscribe_filters(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed(EthNewTransactionFeed()) to = "0x1111111111111111111111111111111111111111" eth_tx_message = generate_new_eth_with_to_transaction(to[2:]) eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BLOCKCHAIN_SOCKET, local_region=True) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" logger.error(expected_tx_hash) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "newTxs", options={"filters": f"to = {to} or to = aaaa"}) self.gateway_node.feed_manager.publish_to_feed( FeedKey("newTxs"), eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) expected_tx_contents = get_expected_eth_tx_contents(eth_tx_message) self.assertEqual(expected_tx_contents, subscription_message.notification["txContents"])
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_eth_pending_transactions_feed_default_subscribe(self): self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue) ) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction( eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET, local_region=True ) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe("pendingTxs") self.gateway_node.feed_manager.publish_to_feed( FeedKey("pendingTxs"), eth_transaction ) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id ) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual( expected_tx_hash, subscription_message.notification["txHash"] )
async def test_eth_new_tx_feed_subscribe_include_from_blockchain(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed(EthNewTransactionFeed()) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BLOCKCHAIN_SOCKET, local_region=True) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "newTxs", {"include_from_blockchain": True}) self.gateway_node.feed_manager.publish_to_feed( FeedKey("newTxs"), eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) expected_tx_contents = get_expected_eth_tx_contents(eth_tx_message) self.assertEqual(expected_tx_contents, subscription_message.notification["txContents"]) self.assertTrue(subscription_message.notification["localRegion"])
async def test_eth_new_transactions_feed_default_subscribe(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed(EthNewTransactionFeed()) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe("newTxs") self.gateway_node.feed_manager.publish_to_feed( "newTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) expected_tx_contents = get_expected_eth_tx_contents(eth_tx_message) self.assertEqual(expected_tx_contents, subscription_message.notification["txContents"])
async def test_eth_new_tx_feed_subscribe_not_include_from_blockchain(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed(EthNewTransactionFeed()) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BDN_SOCKET) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" eth_tx_message_blockchain = generate_new_eth_transaction() eth_transaction_blockchain = EthRawTransaction( eth_tx_message_blockchain.tx_hash(), eth_tx_message_blockchain.tx_val(), FeedSource.BLOCKCHAIN_SOCKET) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "newTxs", {"include_from_blockchain": False}) self.gateway_node.feed_manager.publish_to_feed( "newTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["txHash"]) self.gateway_node.feed_manager.publish_to_feed( "newTxs", eth_transaction_blockchain) with self.assertRaises(asyncio.TimeoutError): await asyncio.wait_for( ws.get_next_subscription_notification_by_id( subscription_id), 0.1)
async def test_subscribe_with_duplicates(self): self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue)) eth_tx_message = generate_new_eth_transaction() eth_transaction = EthRawTransaction(eth_tx_message.tx_hash(), eth_tx_message.tx_val()) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe("pendingTxs", {"duplicates": True}) self.gateway_node.feed_manager.publish_to_feed( "pendingTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["tx_hash"]) # will publish twice self.gateway_node.feed_manager.publish_to_feed( "pendingTxs", eth_transaction) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual(expected_tx_hash, subscription_message.notification["tx_hash"])
async def test_connection_to_invalid_channel(self): async with WsProvider(self.ws_uri) as ws: self.assertEqual(1, len(self.server._connections)) connection_handler = self.server._connections[0] with self.assertRaises(RpcError): _ = await ws.subscribe("fake_channel") await connection_handler.close()
async def process_new_blocks_gateway(gateway_url: str, feed_name: str, exclude_block_contents: bool) -> None: print(f"Initiating connection to: {gateway_url}") async with WsProvider(gateway_url) as ws: print(f"websockets endpoint: {gateway_url} established") global ws_provider ws_provider = cast(WsProvider, ws) await process_new_blocks_bdn(feed_name, exclude_block_contents)
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_pending_transactions_feed_subscribe_filters4(self): self.gateway_node.feed_manager.feeds.clear() self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue) ) to = "0x" eth_tx_message = generate_new_eth_with_to_transaction(to[2:]) eth_transaction = EthRawTransaction( eth_tx_message.tx_hash(), eth_tx_message.tx_val(), FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) expected_tx_hash = f"0x{str(eth_transaction.tx_hash)}" logger.error(expected_tx_hash) to2 = "0x0000000000000000000000000000000000000000" eth_tx_message2 = generate_new_eth_with_to_transaction(to2[2:]) eth_transaction2 = EthRawTransaction( eth_tx_message2.tx_hash(), eth_tx_message2.tx_val(), FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) expected_tx_hash2 = f"0x{str(eth_transaction2.tx_hash)}" logger.error(expected_tx_hash2) async with WsProvider(self.ws_uri) as ws: subscription_id = await ws.subscribe( "pendingTxs", options={ "filters": f"to in [0x0000000000000000000000000000000000000000]" }, ) self.gateway_node.feed_manager.publish_to_feed( FeedKey("pendingTxs"), eth_transaction ) self.gateway_node.feed_manager.publish_to_feed( FeedKey("pendingTxs"), eth_transaction2 ) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id ) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual( expected_tx_hash, subscription_message.notification["txHash"] ) subscription_message = await ws.get_next_subscription_notification_by_id( subscription_id ) self.assertEqual(subscription_id, subscription_message.subscription_id) self.assertEqual( expected_tx_hash2, subscription_message.notification["txHash"] )
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 process_new_blocks_cloud_api( ws_uri: str, auth_header: str, feed_name: str, exclude_block_contents: bool ) -> None: print(f"Initiating connection to: {ws_uri}") async with WsProvider( uri=ws_uri, headers={"Authorization": auth_header} ) as ws: print(f"websockets endpoint: {ws_uri} established") global ws_provider ws_provider = cast(CloudWssProvider, ws) await process_new_blocks_bdn(feed_name, exclude_block_contents)
async def process_new_txs_gateway(gateway_url: str, feed_name: str, exclude_tx_contents: bool, exclude_duplicates: bool, include_from_blockchain: bool, min_gas: Optional[int], addresses: List[str]) -> None: print(f"Initiating connection to: {gateway_url}") async with WsProvider(gateway_url) as ws: print(f"websockets endpoint: {gateway_url} established") global ws_provider ws_provider = cast(WsProvider, ws) await process_new_txs_bdn(feed_name, exclude_tx_contents, exclude_duplicates, include_from_blockchain, min_gas, addresses)
async def process_new_txs_cloud_api(ws_uri: str, auth_header: str, feed_name: str, exclude_tx_contents: bool, exclude_duplicates: bool, exclude_from_blockchain: bool, min_gas: Optional[int], addresses: List[str]) -> None: print(f"Initiating connection to: {ws_uri}") async with WsProvider(uri=ws_uri, headers={"Authorization": auth_header}) as ws: print(f"websockets endpoint: {ws_uri} established") global ws_provider ws_provider = cast(WsProvider, ws) await process_new_txs_bdn(feed_name, exclude_tx_contents, exclude_duplicates, exclude_from_blockchain, min_gas, addresses)
async def test_connection_and_close(self): async with WsProvider(self.ws_uri) as ws: self.assertTrue(ws.running) await self.server._connections[0].close()