def test_is_publisher_allowed(): config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) processor = MetadataCreatedProcessor(event_sample, None, web3, None, None, None, None, None) processor.allowed_publishers = None assert processor.is_publisher_allowed(processor.sender_address) is True
def test_events_monitor_object(monkeypatch): config_file = app.config["AQUARIUS_CONFIG_FILE"] monkeypatch.setenv("ALLOWED_PUBLISHERS", "can not be converted to a set") monitor = EventsMonitor(setup_web3(config_file), config_file) assert monitor._allowed_publishers == set() monkeypatch.setenv("OCN_EVENTS_MONITOR_QUITE_TIME", "can not be converted to int") monitor = EventsMonitor(setup_web3(config_file), config_file) assert monitor._monitor_sleep_time == 10 monkeypatch.setenv("EVENTS_CLEAN_START", "1") with patch("aquarius.events.events_monitor.EventsMonitor.reset_chain" ) as mock: monitor = EventsMonitor(setup_web3(config_file), config_file) mock.assert_called_once()
def test_order_started_processor(): config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) test_account1 = Account.from_key( os.environ.get("EVENTS_TESTS_PRIVATE_KEY", None)) dt_address = deploy_datatoken(web3, test_account1, "TT1", "TT1Symbol") es_instance = Mock() es_instance.read.return_value = { "sample_asset": "mock", "stats": { "orders": 0 } } es_instance.update.return_value = None price_json = { "value": 12.4, "tokenAddress": "test", "tokenSymbol": "test2" } processor = OrderStartedProcessor(dt_address, es_instance, 0, 0) with patch( "aquarius.events.processors.get_number_orders_price") as no_mock: no_mock.return_value = 3, price_json updated_asset = processor.process() assert es_instance.update.called_once() assert updated_asset["stats"]["orders"] == 3 assert updated_asset["stats"]["price"] == price_json
def test_deploy_datatoken_fails(): config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) test_account1 = Account.from_key(os.environ.get("EVENTS_TESTS_PRIVATE_KEY", None)) with patch.object(type(web3.eth), "getTransactionReceipt") as mock: mock.side_effect = Exception() with pytest.raises(Exception, match="tx not found"): deploy_datatoken(web3, test_account1, "TT1", "TT1Symbol")
def test_start_stop_events_monitor(): config_file = app.config["AQUARIUS_CONFIG_FILE"] monitor = EventsMonitor(setup_web3(config_file), config_file) monitor._monitor_is_on = True assert monitor.start_events_monitor() is None monitor = EventsMonitor(setup_web3(config_file), config_file) monitor._contract_address = None assert monitor.start_events_monitor() is None monitor = EventsMonitor(setup_web3(config_file), config_file) monitor._contract = None assert monitor.start_events_monitor() is None monitor = EventsMonitor(setup_web3(config_file), config_file) with patch("aquarius.events.events_monitor.Thread.start") as mock: monitor.start_events_monitor() mock.assert_called_once() monitor.stop_monitor()
def test_drop_non_factory(): dt_factory = Mock() dt_factory.caller = Mock() dt_factory.caller.erc721List.return_value = "not the address" config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) processor = MetadataCreatedProcessor(event_sample, None, None, None, web3, None, None, None) with patch("aquarius.events.processors.get_dt_factory") as mock2: mock2.return_value = dt_factory assert not processor.process()
def test_run_monitor_purgatory(monkeypatch): config_file = app.config["AQUARIUS_CONFIG_FILE"] monkeypatch.setenv( "ASSET_PURGATORY_URL", "https://raw.githubusercontent.com/oceanprotocol/list-purgatory/main/list-assets.json", ) monitor = EventsMonitor(setup_web3(config_file), config_file) monitor._monitor_is_on = True with patch("aquarius.events.purgatory.Purgatory.update_lists") as mock: monitor.do_run_monitor() mock.assert_called_once() with patch("aquarius.events.purgatory.Purgatory.update_lists") as mock: mock.side_effect = Exception("Boom!") monitor.do_run_monitor()
def test_order_started_processor_no_asset(): config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) test_account1 = Account.from_key( os.environ.get("EVENTS_TESTS_PRIVATE_KEY", None)) dt_address = deploy_datatoken(web3, test_account1, "TT1", "TT1Symbol") es_instance = Mock() es_instance.read.return_value = None processor = OrderStartedProcessor(dt_address, es_instance, 0, 0) updated_asset = processor.process() assert not es_instance.update.called assert updated_asset is None
def test_do_decode_update(): config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) processor = MetadataUpdatedProcessor(event_updated_sample, None, web3, None, None, None, None, None) processor.block = 0 old_asset = { "event": { "block": 100, "tx": "placeholder" }, "publicKey": [{ "owner": "some_address" }], } assert processor.check_update(None, old_asset, "") is False
def test_run_monitor(monkeypatch): config_file = app.config["AQUARIUS_CONFIG_FILE"] monitor = EventsMonitor(setup_web3(config_file), config_file) monitor.sleep_time = 1 monitor._monitor_is_on = False assert monitor.do_run_monitor() is None monitor._monitor_is_on = True with patch( "aquarius.events.events_monitor.EventsMonitor.process_current_blocks" ) as mock: mock.side_effect = Exception("Boom!") assert monitor.do_run_monitor() is None with patch( "aquarius.events.events_monitor.EventsMonitor.process_current_blocks" ) as mock: monitor.do_run_monitor() mock.assert_called_once()
def test_process_block_range(client, base_ddo_url, events_object): config_file = app.config["AQUARIUS_CONFIG_FILE"] monitor = EventsMonitor(setup_web3(config_file), config_file) assert monitor.process_block_range( 13, 10) is None # not processing if from > to _ddo = new_ddo(test_account1, get_web3(), "dt.0") send_create_update_tx("create", _ddo, bytes([2]), test_account1) with patch( "aquarius.events.events_monitor.MetadataCreatedProcessor.process" ) as mock: mock.side_effect = Exception("Boom!") assert events_object.process_current_blocks() is None send_create_update_tx("update", _ddo, bytes([2]), test_account1) with patch( "aquarius.events.events_monitor.MetadataUpdatedProcessor.process" ) as mock: mock.side_effect = Exception("Boom!") assert events_object.process_current_blocks() is None
def test_process_fallback(monkeypatch, client, base_ddo_url, events_object): config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) block = web3.eth.block_number _ddo = new_ddo(test_account1, web3, f"dt.{block}") did = _ddo.id send_create_update_tx("create", _ddo, bytes([2]), test_account1) events_object.process_current_blocks() published_ddo = get_ddo(client, base_ddo_url, did) assert published_ddo["id"] == did events_object._es_instance.delete(did) _ddo["metadata"]["name"] = "Updated ddo by event" send_create_update_tx("update", _ddo, bytes(2), test_account1) # falls back on the MetadataCreatedProcessor # since no es instance means read will throw an Exception with patch("aquarius.events.processors.MetadataCreatedProcessor.process" ) as mock: events_object.process_current_blocks() mock.assert_called()
def test_check_metadata_proofs(monkeypatch): # empty env var => everything is validated monkeypatch.delenv("ALLOWED_VALIDATORS", None) assert check_metadata_proofs(None, "whatever_it_works") # wrong env var => nothing is validated monkeypatch.setenv("ALLOWED_VALIDATORS", "not a json") assert not check_metadata_proofs(None, "whatever_it_works") config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) random_addresses = [] random_dicts = [] for i in range(5): random_address = web3.eth.account.create().address random_addresses.append(random_address) random_dicts.append( AttributeDict({"args": AttributeDict({"validator": random_address})}) ) monkeypatch.setenv( "ALLOWED_VALIDATORS", json.dumps([random_addresses[0], random_addresses[1]]) ) assert check_metadata_proofs(web3, [random_dicts[0]]) assert check_metadata_proofs(web3, [random_dicts[1]]) assert not check_metadata_proofs(web3, [random_dicts[2]]) assert not check_metadata_proofs(web3, [random_dicts[2], random_dicts[3]]) assert check_metadata_proofs(web3, [random_dicts[0], random_dicts[3]]) assert check_metadata_proofs(web3, [random_dicts[0], random_dicts[0]]) # no metadata proofs set assert not check_metadata_proofs(web3, []) assert not check_metadata_proofs(web3, []) # no validators set monkeypatch.setenv("ALLOWED_VALIDATORS", json.dumps([])) assert check_metadata_proofs(web3, [random_dicts[4]])
def run_events_monitor(): setup_logging() logger.info("EventsMonitor: preparing") required_env_vars = ["EVENTS_RPC", "AQUARIUS_CONFIG_FILE"] for envvar in required_env_vars: if not os.getenv(envvar): raise AssertionError( f"env var {envvar} is missing, make sure to set the following " f"environment variables before starting the events monitor: {required_env_vars}" ) config_file = os.getenv("AQUARIUS_CONFIG_FILE", "config.ini") monitor = EventsMonitor(setup_web3(config_file, logger), config_file) monitor.start_events_monitor() logger.info("EventsMonitor: started") if os.getenv("EVENTS_HTTP", None): logger.info("Events HTTP probing started on port 5001..") httpd = socketserver.TCPServer(("", 5001), Handler) httpd.serve_forever() else: while True: time.sleep(5)
def trigger_caching(): """Triggers manual caching of a specific transaction (MetadataCreated or MetadataUpdated event) --- tags: - name consumes: - application/json parameters: - name: transactionId required: true description: transaction id containing MetadataCreated or MetadataUpdated event - name: logIndex required: false description: zero-based index in log if transaction contains more events responses: 200: description: successful operation. 400: description: bad request. Log index not found or event not found. 500: description: server error/exception """ try: data = request.args if request.args else request.json tx_id = data.get("transactionId") log_index = int(data.get("logIndex", 0)) config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) tx_receipt = web3.eth.wait_for_transaction_receipt(tx_id) if len(tx_receipt.logs) <= log_index or log_index < 0: return jsonify(error=f"Log index {log_index} not found"), 400 dt_address = tx_receipt.logs[log_index].address dt_contract = web3.eth.contract( abi=ERC721Template.abi, address=web3.toChecksumAddress(dt_address)) created_event = dt_contract.events.MetadataCreated().processReceipt( tx_receipt, errors=DISCARD) updated_event = dt_contract.events.MetadataUpdated().processReceipt( tx_receipt, errors=DISCARD) if not created_event and not updated_event: return jsonify( error="No metadata created/updated event found in tx."), 400 es_instance = ElasticsearchInstance(config_file) allowed_publishers = get_allowed_publishers() purgatory = (Purgatory(es_instance) if (os.getenv("ASSET_PURGATORY_URL") or os.getenv("ACCOUNT_PURGATORY_URL")) else None) chain_id = web3.eth.chain_id processor_args = [ es_instance, web3, allowed_publishers, purgatory, chain_id ] processor = (MetadataCreatedProcessor if created_event else MetadataUpdatedProcessor) event_to_process = created_event[ 0] if created_event else updated_event[0] event_processor = processor( *([event_to_process, dt_contract, tx_receipt["from"]] + processor_args)) event_processor.process() did = make_did(dt_address, chain_id) response = app.response_class( response=sanitize_record(es_instance.get(did)), status=200, mimetype="application/json", ) return response except Exception as e: logger.error(f"trigger_caching failed: {str(e)}.") return ( jsonify( error=f"Encountered error when triggering caching: {str(e)}."), 500, )
def test_missing_attributes(): config_file = app.config["AQUARIUS_CONFIG_FILE"] web3 = setup_web3(config_file) test_account1 = Account.from_key( os.environ.get("EVENTS_TESTS_PRIVATE_KEY", None)) dt_address = deploy_datatoken(web3, test_account1, "TT1", "TT1Symbol") dt_contract = web3.eth.contract(abi=ERC721Template.abi, address=web3.toChecksumAddress(dt_address)) dt_factory = Mock() dt_factory.caller = Mock() dt_factory.caller.erc721List.return_value = ( "0x0000000000000000000000000000000000000000") processor = MetadataCreatedProcessor(event_sample, None, None, None, web3, None, None, None) assert processor._get_contract_attribute(dt_contract, "non_existent") == "" assert processor._get_contract_attribute(dt_contract, "symbol") == "TT1Symbol" processor.dt_contract = Mock(spec=ERC721Template) processor.caller = Mock() processor.caller.ownerOf.side_effect = Exception() assert processor.get_nft_owner() == "" processor.event = Mock() processor.event.args.decryptorUrl = "" processor.event.args.metaDataHash = "" processor.event.args.address = "" processor.event.address = "0x0000000000000000000000000000000000000000" with patch("aquarius.events.processors.decrypt_ddo") as mock: mock.return_value = None with patch("aquarius.events.processors.get_dt_factory") as mock2: mock2.return_value = dt_factory with pytest.raises(Exception, match="Decrypt ddo failed"): processor.process() processor = MetadataUpdatedProcessor(event_sample, None, None, None, web3, None, None, None) assert processor._get_contract_attribute(dt_contract, "non_existent") == "" assert processor._get_contract_attribute(dt_contract, "symbol") == "TT1Symbol" processor.dt_contract = Mock(spec=ERC721Template) processor.caller = Mock() processor.caller.ownerOf.side_effect = Exception() assert processor.get_nft_owner() == "" processor.event = Mock() processor.event.args.decryptorUrl = "" processor.event.args.metaDataHash = "" processor.event.address = "0x0000000000000000000000000000000000000000" with patch("aquarius.events.processors.decrypt_ddo") as mock: mock.return_value = None with patch("aquarius.events.processors.get_dt_factory") as mock2: mock2.return_value = dt_factory with pytest.raises(Exception, match="Decrypt ddo failed"): processor.process()
id=index_name, body=record, doc_type="_doc", refresh="wait_for", )["_id"] print("OK") def get_status(): if Elasticsearch(config.db_url).ping(): return "Elasticsearch connected", 200 else: return "Not connected to any database", 400 # Start events monitoring if required if get_bool_env_value("EVENTS_ALLOW", 0): config_file = app.config["AQUARIUS_CONFIG_FILE"] monitor = EventsMonitor(setup_web3(config_file), config_file) monitor.start_events_monitor() if __name__ == "__main__": if isinstance(config.aquarius_url.split(":")[-1], int): app.run( host=config.aquarius_url.split(":")[1], port=config.aquarius_url.split(":")[-1], ) else: app.run()
def test_setup_web3(monkeypatch): config_file = app.config["AQUARIUS_CONFIG_FILE"] monkeypatch.setenv("NETWORK_NAME", "rinkeby") assert setup_web3(config_file, logger)