def test_msg_tx(self): self.node.feed_manager.publish_to_feed = MagicMock() self.node.opts.ws = True self.node.opts.transaction_validation = False transaction = mock_eth_messages.get_dummy_transaction(1) transaction_hash = transaction.hash() transaction_contents = transaction.contents() messages = TransactionsEthProtocolMessage(None, [transaction]) self.sut.msg_tx(messages) # published to both feeds self.node.feed_manager.publish_to_feed.assert_has_calls( [ call( FeedKey(EthNewTransactionFeed.NAME), EthRawTransaction( transaction_hash, transaction_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) ), call( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction( transaction_hash, transaction_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=True ) ), ] ) # broadcast transactions self.assertEqual(1, len(self.broadcast_messages)) self.assertEqual(1, len(self.broadcast_to_node_messages))
async def test_eth_pending_tx_feed_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(), 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": True}) 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 publish twice 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_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_default_subscribe(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_result = { "blockHash": "0xe6f67c6948158c45dct10b169ad6bf3a96c6402489733a03051feaf7d09e7b54", "blockNumber": "0xaf25e5", "cumulativeGasUsed": "0xbdb9ae", "from": "0x82170dd1cec50107963bf1ba1e80955ea302c5ce", "gasUsed": "0x5208", "logs": [], "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "status": "0x1", "to": "0xa09f63d9a0b0fbe89e41e51282ad660e7c876165", "transactionHash": "0xbcdc5b22bf463f9b8766dd61cc133caf13472b6ae8474061134d9dc2983625f6", "transactionIndex": "0x90" } self.gateway_node.eth_ws_proxy_publisher.call_rpc = AsyncMock( return_value=JsonRpcResponse(request_id=1, result=receipt_result)) block = mock_eth_messages.get_dummy_block(5) internal_block_info = InternalEthBlockInfo.from_new_block_msg( NewBlockEthProtocolMessage(None, block, 1)) eth_raw_block_1 = EthRawBlock(1, internal_block_info.block_hash(), FeedSource.BLOCKCHAIN_RPC, get_block_message_lazy(None)) eth_raw_block_2 = EthRawBlock( 1, internal_block_info.block_hash(), FeedSource.BLOCKCHAIN_SOCKET, 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) self.gateway_node.feed_manager.publish_to_feed( FeedKey(rpc_constants.ETH_TRANSACTION_RECEIPTS_FEED_NAME), eth_raw_block_1) self.gateway_node.feed_manager.publish_to_feed( FeedKey(rpc_constants.ETH_TRANSACTION_RECEIPTS_FEED_NAME), eth_raw_block_2) 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_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_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"])
def msg_confirmed_tx(self, msg: ConfirmedTxMessage) -> None: tx_hash = msg.tx_hash() transaction_key = self.node.get_tx_service().get_transaction_key( tx_hash) tx_contents = msg.tx_val() # shouldn't ever happen, but just in case if tx_contents == ConfirmedTxMessage.EMPTY_TX_VAL: tx_contents = cast( Optional[memoryview], self.node.get_tx_service().get_transaction_by_key( transaction_key)) if tx_contents is None: transaction_feed_stats_service.log_pending_transaction_missing_contents( ) return self.node.feed_manager.publish_to_feed( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BDN_SOCKET, local_region=True)) transaction_feed_stats_service.log_pending_transaction_from_internal( tx_hash)
def _publish_block_to_on_block_feed( self, raw_block: EthRawBlock, ) -> None: if raw_block.source in EthOnBlockFeed.VALID_SOURCES: self.feed_manager.publish_to_feed( FeedKey(EthOnBlockFeed.NAME), EventNotification(raw_block.block_number))
def publish_new_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview, local_region: bool) -> None: self.node.feed_manager.publish_to_feed( FeedKey(NewTransactionFeed.NAME), RawTransactionFeedEntry(tx_hash, tx_contents, local_region=local_region))
def _publish_block_to_on_block_feed( self, raw_block: EthRawBlock, ) -> None: if raw_block.source in {FeedSource.BLOCKCHAIN_RPC}: self.feed_manager.publish_to_feed( FeedKey(EthOnBlockFeed.NAME), EventNotification(raw_block.block_number))
def publish_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview, local_region: bool = True) -> None: transaction_feed_stats_service.log_new_transaction(tx_hash) self.node.feed_manager.publish_to_feed( FeedKey(EthNewTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=local_region)) transaction_feed_stats_service.log_pending_transaction_from_local( tx_hash) self.node.feed_manager.publish_to_feed( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BLOCKCHAIN_SOCKET, local_region=local_region))
def publish_new_transaction(self, tx_hash: Sha256Hash, tx_contents: memoryview, local_region: bool) -> None: gas_price = eth_common_utils.raw_tx_gas_price(tx_contents, 0) if gas_price >= self.node.get_network_min_transaction_fee(): self.node.feed_manager.publish_to_feed( FeedKey(EthNewTransactionFeed.NAME), EthRawTransaction(tx_hash, tx_contents, FeedSource.BDN_SOCKET, local_region=local_region))
def process_transaction_with_contents(self, transaction_key: TransactionKey, tx_contents: memoryview) -> None: transaction_feed_stats_service.log_pending_transaction_from_local( transaction_key.transaction_hash) self.feed_manager.publish_to_feed( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction(transaction_key.transaction_hash, tx_contents, FeedSource.BLOCKCHAIN_RPC, local_region=True))
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, local_region=True ) 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, local_region=True ) 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(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"] ) self.gateway_node.feed_manager.publish_to_feed( FeedKey("newTxs"), eth_transaction_blockchain ) with self.assertRaises(asyncio.TimeoutError): await asyncio.wait_for( ws.get_next_subscription_notification_by_id(subscription_id), 0.1 )
def test_publish_new_tx_from_different_location(self): # relay from different region bx_tx_message_2 = self._convert_to_bx_message( mock_eth_messages.EIP_155_TRANSACTIONS_MESSAGE) self.node.feed_manager.publish_to_feed = MagicMock() self.relay_connection_2.msg_tx(bx_tx_message_2) expected_publication = EthRawTransaction(bx_tx_message_2.tx_hash(), bx_tx_message_2.tx_val(), FeedSource.BDN_SOCKET, local_region=False) self.node.feed_manager.publish_to_feed.assert_called_once_with( FeedKey(NewTransactionFeed.NAME), expected_publication)
def validate_params_get_options(self): params = self.params if not isinstance(params, list) or len(params) != 2: raise RpcInvalidParams( self.request_id, "Subscribe RPC request params must be a list of length 2.", ) feed_name, options = params self.feed_name = feed_name self.feed_key = FeedKey(self.feed_name, self.feed_network) self.options = options
def test_publish_new_transaction(self): bx_tx_message = self._convert_to_bx_message( mock_eth_messages.EIP_155_TRANSACTIONS_MESSAGE) bx_tx_message.set_transaction_flag(TransactionFlag.LOCAL_REGION) self.node.feed_manager.publish_to_feed = MagicMock() self.relay_connection_1.msg_tx(bx_tx_message) expected_publication = EthRawTransaction(bx_tx_message.tx_hash(), bx_tx_message.tx_val(), FeedSource.BDN_SOCKET, local_region=True) self.node.feed_manager.publish_to_feed.assert_called_once_with( FeedKey(NewTransactionFeed.NAME), expected_publication)
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), FeedSource.BDN_SOCKET, False ) serialized_published_message = RawTransactionFeedEntry( raw_published_message.tx_hash, raw_published_message.tx_contents, raw_published_message.local_region ) self.gateway_node.feed_manager.publish_to_feed( FeedKey("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["txHash"], ) self.assertEqual( serialized_published_message.tx_contents, subscription_message.notification["txContents"], ) self.assertFalse( subscription_message.notification["localRegion"], ) 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)
def process_transaction_with_parsed_contents( self, transaction_key: TransactionKey, parsed_tx: Optional[Dict[str, Any]] ) -> None: transaction_feed_stats_service.log_pending_transaction_from_local(transaction_key.transaction_hash) if parsed_tx is None: logger.debug(log_messages.TRANSACTION_NOT_FOUND_IN_MEMPOOL, transaction_key.transaction_hash) transaction_feed_stats_service.log_pending_transaction_missing_contents() else: gas_price = int(parsed_tx["gasPrice"], 16) if gas_price >= self.node.get_network_min_transaction_fee(): self.feed_manager.publish_to_feed( FeedKey(EthPendingTransactionFeed.NAME), EthRawTransaction( transaction_key.transaction_hash, parsed_tx, FeedSource.BLOCKCHAIN_RPC, local_region=True, ) )
async def setUp(self) -> None: crypto_utils.recover_public_key = MagicMock(return_value=bytes(32)) account_model = BdnAccountModelBase( "account_id", "account_name", "fake_certificate", new_transaction_streaming=BdnServiceModelConfigBase( expire_date=date(2999, 1, 1).isoformat())) self.eth_ws_port = helpers.get_free_port() self.eth_ws_uri = f"ws://127.0.0.1:{self.eth_ws_port}" self.eth_ws_server_message_queue = asyncio.Queue() await self.start_server() gateway_opts = gateway_helpers.get_gateway_opts( 8000, eth_ws_uri=self.eth_ws_uri, ws=True) gateway_opts.set_account_options(account_model) self.gateway_node = MockGatewayNode(gateway_opts) self.gateway_node.transaction_streamer_peer = OutboundPeerModel( "127.0.0.1", 8006, node_type=NodeType.INTERNAL_GATEWAY) self.gateway_node.feed_manager.register_feed( EthPendingTransactionFeed(self.gateway_node.alarm_queue)) self.eth_ws_proxy_publisher = EthWsProxyPublisher( self.eth_ws_uri, self.gateway_node.feed_manager, self.gateway_node.get_tx_service(), self.gateway_node) self.subscriber: Subscriber[ RawTransactionFeedEntry] = self.gateway_node.feed_manager.subscribe_to_feed( FeedKey(EthPendingTransactionFeed.NAME), {}) self.assertIsNotNone(self.subscriber) await self.eth_ws_proxy_publisher.start() await asyncio.sleep(0.01) self.assertEqual(len(self.eth_ws_proxy_publisher.receiving_tasks), 2) self.assertEqual(0, self.subscriber.messages.qsize()) self.sample_transactions = { i: mock_eth_messages.get_dummy_transaction(i) for i in range(10) }
def __init__( self, request: BxJsonRpcRequest, node: "AbstractNode", feed_manager: FeedManager, subscribe_handler: Callable[[Subscriber, FeedKey], None], feed_network: int = 0, account_details: Optional[BdnAccountModelBase] = None) -> None: self.feed_name = "" self.feed_network = feed_network self.feed_key = FeedKey(self.feed_name, self.feed_network) self.feed_manager = feed_manager self.subscribe_handler = subscribe_handler self.options = {} self.available_fields = [] self.all_fields = [] self.account_details = account_details self.service_model: Optional[BdnFeedServiceModelConfigBase] = None super().__init__(request, node) assert self.feed_name != ""
async def test_unsubscribe(self): feed = TestFeed("foo") self.feed_manager.register_feed(feed) subscribe_request = BxJsonRpcRequest("1", RpcRequestType.SUBSCRIBE, ["foo", {}]) rpc_handler = self.rpc.get_request_handler(subscribe_request) result = await rpc_handler.process_request() subscriber_id = result.result # message is received next_message_task: Future[BxJsonRpcRequest] = asyncio.ensure_future( self.rpc.get_next_subscribed_message()) await asyncio.sleep(0) self.assertFalse(next_message_task.done()) feed.publish("foobar") await asyncio.sleep(0) # publish to subscriber await asyncio.sleep(0) # subscriber publishes to queue self.assertTrue(next_message_task.done()) unsubscribe_request = BxJsonRpcRequest("1", RpcRequestType.UNSUBSCRIBE, [subscriber_id]) rpc_handler = self.rpc.get_request_handler(unsubscribe_request) result = await rpc_handler.process_request() self.assertTrue(result.result) next_message_task: Future[BxJsonRpcRequest] = asyncio.ensure_future( self.rpc.get_next_subscribed_message()) feed.publish("foobar_not_received") feed.publish("foobar_not_received_2") await asyncio.sleep(0) # publish to subscriber await asyncio.sleep(0) # subscriber publishes to queue self.assertFalse(next_message_task.done()) # no message self.assertEqual(0, len(self.rpc.subscriptions)) self.assertEqual( 0, self.feed_manager.get_feed(FeedKey("foo")).subscriber_count())
async def test_subscribe_to_feed(self): feed = TestFeed("foo") self.feed_manager.register_feed(feed) subscribe_request = BxJsonRpcRequest("1", RpcRequestType.SUBSCRIBE, ["foo", {}]) rpc_handler = self.rpc.get_request_handler(subscribe_request) self.assertIsInstance(rpc_handler, SubscribeRpcRequest) result = await rpc_handler.process_request() self.assertIsNotNone(result.result) self.assertIsNone(result.error) subscriber_id = result.result self.assertEqual( 1, self.feed_manager.get_feed(FeedKey("foo")).subscriber_count()) self.assertEqual(1, len(self.rpc.subscriptions)) self.assertIn(subscriber_id, self.rpc.subscriptions) next_message_task: Future[BxJsonRpcRequest] = asyncio.ensure_future( self.rpc.get_next_subscribed_message()) await asyncio.sleep(0) self.assertFalse(next_message_task.done()) feed.publish("foobar") await asyncio.sleep(0) # publish to subscriber await asyncio.sleep(0) # subscriber publishes to queue self.assertTrue(next_message_task.done()) next_message = next_message_task.result() self.assertEqual("2.0", next_message.json_rpc_version) self.assertEqual(RpcRequestType.SUBSCRIBE, next_message.method) self.assertEqual(subscriber_id, next_message.params["subscription"]) self.assertEqual("foobar", next_message.params["result"])
def _publish_block_to_transaction_receipts_feed(self, raw_block: EthRawBlock): self.feed_manager.publish_to_feed( FeedKey(EthTransactionReceiptsFeed.NAME), raw_block)
def _publish_block_to_new_block_feed( self, raw_block: EthRawBlock, ) -> None: self.feed_manager.publish_to_feed(FeedKey(EthNewBlockFeed.NAME), raw_block)
def get_info(self) -> Dict[str, Any]: interval_data = self.interval_data if len(interval_data.new_transactions_faster_than_pending_times) > 0: avg_new_transactions_faster_by_s = ( sum(interval_data.new_transactions_faster_than_pending_times) / len(interval_data.new_transactions_faster_than_pending_times)) else: avg_new_transactions_faster_by_s = 0 new_transactions_faster_count = len([ diff for diff in interval_data.new_transactions_faster_than_pending_times if diff > 0 ]) if len(interval_data.pending_from_internal_faster_than_local_times ) > 0: avg_pending_transactions_from_internal_faster_by_s = (sum( interval_data.pending_from_internal_faster_than_local_times ) / len( interval_data.pending_from_internal_faster_than_local_times)) else: avg_pending_transactions_from_internal_faster_by_s = 0 pending_transactions_from_internal_faster_count = len([ diff for diff in interval_data.pending_from_internal_faster_than_local_times if diff > 0 ]) node = self.node assert node is not None feeds = node.feed_manager.feeds pending_transaction_feed = node.feed_manager.get_feed( FeedKey(EthPendingTransactionFeed.NAME)) if pending_transaction_feed: pending_transaction_feed_subscribers = len( pending_transaction_feed.subscribers) else: pending_transaction_feed_subscribers = None new_transaction_feed = node.feed_manager.get_feed( FeedKey(EthNewTransactionFeed.NAME)) if new_transaction_feed: new_transaction_feed_subscribers = len( new_transaction_feed.subscribers) else: new_transaction_feed_subscribers = None return { "start_time": self.interval_data.start_time, "end_time": self.interval_data.end_time, "new_transactions": len(interval_data.new_transaction_received_times), "pending_transactions": len(interval_data.pending_transaction_received_times), "pending_transactions_from_internal": len(interval_data.pending_transaction_from_internal_received_times ), "pending_transactions_from_local": len(interval_data. pending_transaction_from_local_blockchain_received_times), "avg_new_transactions_faster_by_s": avg_new_transactions_faster_by_s, "new_transactions_faster_count": new_transactions_faster_count, "avg_pending_transactions_from_internal_faster_by_s": avg_pending_transactions_from_internal_faster_by_s, "pending_transactions_from_internal_faster_count": pending_transactions_from_internal_faster_count, "pending_transactions_missing_contents": interval_data.pending_transactions_missing_contents, "pending_transaction_feed_subscribers": pending_transaction_feed_subscribers, "new_transaction_feed_subscribers": new_transaction_feed_subscribers, "gateway_transaction_streamers": node.get_gateway_transaction_streamers_count() }
def __contains__(self, item): if isinstance(item, FeedKey): return item in self.feeds else: return FeedKey(item) in self.feeds