def setup_keeper(config_file=None): config = Config(filename=config_file) if config_file else get_config() keeper_url = config.keeper_url artifacts_path = get_keeper_path(config) ContractHandler.artifacts_path = artifacts_path Web3Provider.get_web3(keeper_url) init_account_envvars() account = get_account(0) if account is None: raise AssertionError( f'Nevermined Gateway cannot run without a valid ' f'ethereum account. Account address was not found in the environment' f'variable `PROVIDER_ADDRESS`. Please set the following environment ' f'variables and try again: `PROVIDER_ADDRESS`, `PROVIDER_PASSWORD`, ' f', `PROVIDER_KEYFILE`, `RSA_KEYFILE` and `RSA_PASSWORD`.') if not account.key_file and not (account.password and account.key_file): raise AssertionError( f'Nevermined Gateway cannot run without a valid ' f'ethereum account with either a password and ' f'keyfile/encrypted-key-string ' f'or private key. Current account has password {account.password}, ' f'keyfile {account.key_file}, encrypted-key {account._encrypted_key} ' f'and private-key {account._private_key}.')
def setup_all(): config = get_config() keeper_url = config.keeper_url Web3Provider.get_web3(keeper_url) ContractHandler.artifacts_path = os.path.expanduser( '~/.nevermined/nevermined-contracts/artifacts') init_account_envvars()
def test_create_data_asset(publisher_instance, consumer_instance, ddo_sample): """ Setup accounts and asset, register this asset on Nevermined Metadata. """ logging.debug("".format()) ########################################################## # Setup 2 accounts ########################################################## publisher_acct = publisher_instance.main_account consumer_acct = consumer_instance.main_account # ensure Nevermined token balance if publisher_instance.accounts.balance(publisher_acct).ocn == 0: rcpt = publisher_instance.accounts.request_tokens(publisher_acct, 200) Web3Provider.get_web3().eth.waitForTransactionReceipt(rcpt) if consumer_instance.accounts.balance(consumer_acct).ocn == 0: rcpt = consumer_instance.accounts.request_tokens(consumer_acct, 200) Web3Provider.get_web3().eth.waitForTransactionReceipt(rcpt) # You will need some token to make this transfer! assert publisher_instance.accounts.balance(publisher_acct).ocn > 0 assert consumer_instance.accounts.balance(consumer_acct).ocn > 0 ########################################################## # Create an Asset with valid metadata ########################################################## asset = ddo_sample ########################################################## # List currently published assets ########################################################## meta_data_assets = publisher_instance.assets.search('') if meta_data_assets: print("Currently registered assets:") print(meta_data_assets) if asset.did in meta_data_assets: publisher_instance.assets.resolve(asset.did) publisher_instance.assets.retire(asset.did) # Publish the metadata new_asset = publisher_instance.assets.create(asset.metadata, publisher_acct) # get_asset_metadata only returns 'main' key, is this correct? published_metadata = consumer_instance.assets.resolve(new_asset.did) assert published_metadata # only compare top level keys assert sorted(list( asset.metadata['main'].keys())).remove('files') == sorted( list(published_metadata.metadata.keys())).remove('encryptedFiles') publisher_instance.assets.retire(new_asset.did)
def _create_filter(self): chain_id = Web3Provider.get_web3().net.version from_block = 0 # temporary workaround to work with mumbai # Infura has a 1000 block range limit in their api if chain_id == '80001': latest_block = Web3Provider.get_web3().eth.get_block_number() from_block = latest_block - 990 self._filter = { 'fromBlock': from_block, 'toBlock': self.block_range[1], 'argument_filters': self.argument_filters }
def _verify_service_agreement_signature(self, did, agreement_id, service_index, consumer_address, signature, ddo=None): """ Verify service agreement signature. Verify that the given signature is truly signed by the `consumer_address` and represents this did's service agreement.. :param did: DID, str :param agreement_id: id of the agreement, hex str :param service_index: identifier of the service inside the asset DDO, str :param consumer_address: ethereum account address of consumer, hex str :param signature: Signature, str :param ddo: DDO instance :return: True if signature is legitimate, False otherwise :raises: ValueError if service is not found in the ddo :raises: AssertionError if conditions keys do not match the on-chain conditions keys """ if not ddo: ddo = self._asset_resolver.resolve(did) service_agreement = ddo.get_service_by_index(service_index) agreement_hash = service_agreement.get_service_agreement_hash( agreement_id, ddo.asset_id, consumer_address, Web3Provider.get_web3().toChecksumAddress(ddo.proof['creator']), self._keeper) recovered_address = self._keeper.personal_ec_recover(agreement_hash, signature) is_valid = (recovered_address == consumer_address) if not is_valid: logger.warning(f'Agreement signature failed: agreement hash is {agreement_hash.hex()}') return is_valid
def test_init_events_monitor(keeper, web3, storage_path, provider_account): events_monitor = ProviderEventsMonitor(keeper, web3, storage_path, provider_account) assert events_monitor.last_n_blocks == events_monitor.LAST_N_BLOCKS assert (Web3Provider.get_web3().eth.blockNumber - events_monitor.latest_block) < 5 assert events_monitor.last_processed_block == 0
def get_network_id(): """ Return the ethereum network id calling the `web3.version.network` method. :return: Network id, int """ return int(Web3Provider.get_web3().net.version)
def get_registered_attribute(self, did_bytes): """ Example of event logs from event_filter.get_all_entries(): [AttributeDict( {'args': AttributeDict( {'did': b'\x02n\xfc\xfb\xfdNM\xe9\xb8\xe0\xba\xc2\xb2\xc7\xbeg\xc9/\x95\xc3\x16\ x98G^\xb9\xe1\xf0T\xce\x83\xcf\xab', 'owner': '0xAd12CFbff2Cb3E558303334e7e6f0d25D5791fc2', 'value': 'http://localhost:5000', 'checksum': '0x...', 'updatedAt': 1947}), 'event': 'DIDAttributeRegistered', 'logIndex': 0, 'transactionIndex': 1, 'transactionHash': HexBytes( '0xea9ca5748d54766fb43fe9660dd04b2e3bb29a0fbe18414457cca3dd488d359d'), 'address': '0x86DF95937ec3761588e6DEbAB6E3508e271cC4dc', 'blockHash': HexBytes( '0xbbbe1046b737f33b2076cb0bb5ba85a840c836cf1ffe88891afd71193d677ba2'), 'blockNumber': 1947})] """ result = None did = Web3.toHex(did_bytes) block_number = self.get_block_number_updated(did_bytes) logger.debug(f'got blockNumber {block_number} for did {did}') if block_number == 0: raise DIDNotFound( f'DID "{did}" is not found on-chain in the current did registry. ' f'Please ensure assets are registered in the correct keeper contracts. ' f'The keeper-contracts DIDRegistry address is {self.address}.' f'Also ensure that sufficient time has passed after registering the asset ' f'such that the transaction is confirmed by the network validators.' ) events = Web3Provider.get_web3().eth.getLogs({ 'fromBlock': block_number, 'toBlock': block_number, 'address': self.contract.address }) event_data = self._filter_did_registered_events(did_bytes, events) if event_data: result = { 'checksum': event_data.args._checksum, 'value': event_data.args._value, 'block_number': block_number, 'did_bytes': event_data.args._did, 'owner': Web3.toChecksumAddress(event_data.args._owner), } else: logger.warning( f'Could not find {DIDRegistry.DID_REGISTRY_EVENT_NAME} event logs for ' f'did {did} at blockNumber {block_number}') return result
def get_eth_from_faucet(config, address): payload = {'address': Web3Provider.get_web3().toChecksumAddress(address), 'agent': 'sdk-py'} response = Faucet._http_client.post(Faucet.get_faucet_url(config), data=payload, headers={'Accept': 'application/json'}) if not response.ok: raise ValueError(response.text) return response
def check(self, token): """ :param token: hex str consist of signature and timestamp :return: hex str ethereum address """ parts = token.split('-') if len(parts) < 2: return '0x0' sig, timestamp = parts if self._get_timestamp() > (int(timestamp) + self._get_expiration()): return '0x0' message = self._get_message(timestamp) address = self._keeper.personal_ec_recover( Web3Provider.get_web3().keccak(text=message), sig) return Web3Provider.get_web3().toChecksumAddress(address)
def get_ether_balance(address): """ Get balance of an ethereum address. :param address: address, bytes32 :return: balance, int """ return Web3Provider.get_web3().eth.getBalance( address, block_identifier='latest')
def unlock_account(account): """ Unlock the account. :param account: Account :return: """ return Web3Provider.get_web3().unlockAccount(account.address, account.password)
def refund_reward(event, agreement_id, did, service_agreement, price, consumer_account, publisher_address, condition_ids, escrow_condition_id): """ Refund the reward to the publisher address. :param event: AttributeDict with the event data. :param agreement_id: id of the agreement, hex str :param did: DID, str :param service_agreement: ServiceAgreement instance :param price: Asset price, int :param consumer_account: Account instance of the consumer :param publisher_address: ethereum account address of publisher, hex str :param condition_ids: is a list of bytes32 content-addressed Condition IDs, bytes32 :param escrow_condition_id: hex str the id of escrow reward condition at this `agreement_id` """ logger.debug( f"trigger refund (agreement {agreement_id}) after event {event}.") if Keeper.get_instance().condition_manager.get_condition_state( escrow_condition_id) > 1: logger.debug( f'escrow payment condition already fulfilled/aborted: ' f'agreementId={agreement_id}, escrow reward conditionId={escrow_condition_id},' f' publisher={publisher_address}') return access_id, lock_id = condition_ids[:2] name_to_parameter = { param.name: param for param in service_agreement.condition_by_name['escrowPayment'].parameters } document_id = add_0x_prefix(name_to_parameter['_documentId'].value) asset_id = add_0x_prefix(did_to_id(did)) did_owner = Keeper.get_instance( ).agreement_manager.get_agreement_did_owner(agreement_id) assert document_id == asset_id, f'document_id {document_id} <=> asset_id {asset_id} mismatch.' assert price == service_agreement.get_price(), 'price mismatch.' try: escrow_condition = Keeper.get_instance().escrow_payment_condition tx_hash = escrow_condition.fulfill( agreement_id, price, Web3Provider.get_web3().toChecksumAddress(did_owner), consumer_account.address, lock_id, access_id, consumer_account) process_tx_receipt( tx_hash, getattr(escrow_condition.contract.events, escrow_condition.FULFILLED_EVENT)(), 'EscrowReward.Fulfilled') except Exception as e: logger.error( f'Error when doing escrow_payment_condition.fulfills (agreementId {agreement_id}): {e}', exc_info=1) raise e
def _load_from_address(address, abi, contract_name): """Retrieve the contract instance for `contract_name` that represent the smart contract in the keeper network. :param contract_name: str name of the solidity keeper contract without the network name. :return: web3.eth.Contract instance """ address = Web3.toChecksumAddress(address) contract = Web3Provider.get_web3().eth.contract(address=address, abi=abi) ContractHandler._contracts[contract_name] = (contract, 'external') return ContractHandler._contracts[contract_name]
def used_by(provenance_id, did, consumer_address, activity_id, signature, attributes, account, keeper): try: receipt = keeper.did_registry.used( convert_to_bytes(provenance_id), convert_to_bytes(did), convert_to_bytes(consumer_address), convert_to_bytes(Web3Provider.get_web3().keccak(text=activity_id)), signature, account, attributes) return bool(receipt and receipt.status == 1) except Exception as e: logging.debug(f'On-chain call error: {e}') return False
def get(self, account): """ :param account: Account instance signing the token :return: hex str the token generated/signed by account """ _message, _time = self._get_message_and_time() msg_hash = Web3Provider.get_web3().keccak(text=_message) try: prefixed_msg_hash = self._keeper.sign_hash( add_ethereum_prefix_and_hash_msg(msg_hash), account) return f'{prefixed_msg_hash}-{_time}' except Exception as e: logging.error(f'Error signing token: {str(e)}')
def sign_hash(msg_hash, account): """ This method use `personal_sign`for signing a message. This will always prepend the `\x19Ethereum Signed Message:\n32` prefix before signing. :param msg_hash: :param account: Account :return: signature """ wallet = Wallet(Web3Provider.get_web3(), account.key_file, account.password, account.address) s = wallet.sign(msg_hash) return s.signature.hex()
def agreements(): publisher_acc = get_publisher_account() keeper = Keeper.get_instance() w3 = Web3Provider.get_web3() did_resolver = Mock() ddo = get_ddo_sample() service = ddo.get_service(ServiceTypes.ASSET_ACCESS) service.update_value(ServiceAgreementTemplate.TEMPLATE_ID_KEY, w3.toChecksumAddress(publisher_acc.address)) did_resolver.resolve = MagicMock(return_value=ddo) return Agreements(keeper, did_resolver, AssetConsumer, AssetExecutor, ConfigProvider.get_config())
def fulfill_escrow_reward_condition(event, agreement_id, service_agreement, price, consumer_address, publisher_account, condition_ids, escrow_condition_id): """ :param event: AttributeDict with the event data. :param agreement_id: id of the agreement, hex str :param service_agreement: ServiceAgreement instance :param price: Asset price, int :param consumer_address: ethereum account address of consumer, hex str :param publisher_account: Account instance of the publisher :param condition_ids: is a list of bytes32 content-addressed Condition IDs, bytes32 :param escrow_condition_id: hex str the id of escrow reward condition at this `agreement_id` :return: """ if not event: logger.warning(f'`fulfill_escrow_reward_condition` got empty event: ' f'event listener timed out.') return keeper = Keeper.get_instance() if keeper.condition_manager.get_condition_state(escrow_condition_id) > 1: logger.debug( f'escrow reward condition already fulfilled/aborted: ' f'agreementId={agreement_id}, escrow reward conditionId={escrow_condition_id}' ) return logger.debug( f"release reward (agreement {agreement_id}) after event {event}.") access_id, lock_id = condition_ids[:2] logger.debug(f'fulfill_escrow_reward_condition: ' f'agreementId={agreement_id}' f'price={price}, {type(price)}' f'consumer={consumer_address},' f'publisher={publisher_account.address},' f'conditionIds={condition_ids}') assert price == service_agreement.get_price(), 'price mismatch.' assert isinstance( price, int), f'price expected to be int type, got type "{type(price)}"' time.sleep(5) keeper = Keeper.get_instance() did_owner = keeper.agreement_manager.get_agreement_did_owner(agreement_id) args = (agreement_id, price, Web3Provider.get_web3().toChecksumAddress(did_owner), consumer_address, lock_id, access_id, publisher_account) process_fulfill_condition(args, keeper.escrow_reward_condition, escrow_condition_id, logger, keeper, 10)
def ec_recover(message, signed_message): """ This method does not prepend the message with the prefix `\x19Ethereum Signed Message:\n32`. The caller should add the prefix to the msg/hash before calling this if the signature was produced for an ethereum-prefixed message. :param message: :param signed_message: :return: """ w3 = Web3Provider.get_web3() v, r, s = split_signature(w3, w3.toBytes(hexstr=signed_message)) signature_object = SignatureFix(vrs=(v, big_endian_to_int(r), big_endian_to_int(s))) return w3.eth.account.recoverHash( message, signature=signature_object.to_hex_v_hacked())
def send_transaction(self, fn_name, fn_args, transact=None): """Calls a smart contract function using either `personal_sendTransaction` (if passphrase is available) or `ether_sendTransaction`. :param fn_name: str the smart contract function name :param fn_args: tuple arguments to pass to function above :param transact: dict arguments for the transaction such as from, gas, etc. :return: """ contract_fn = getattr(self.contract.functions, fn_name)(*fn_args) contract_function = CustomContractFunction( contract_fn ) if transact is not None and 'chainId' not in transact: transact['chainId'] = int(Web3Provider.get_web3().net.version) return contract_function.transact(transact)
def was_associated_with(self, prov_id, did, agent_id, activity_id, account, attributes=None): tx_hash = self.send_transaction( 'wasAssociatedWith', (prov_id, did, agent_id, activity_id, attributes), transact={ 'from': account.address, 'passphrase': account.password, 'keyfile': account.key_file }) return Web3Provider.get_web3().eth.waitForTransactionReceipt( tx_hash, timeout=20)
def get_tx_receipt(tx_hash): """ Get the receipt of a tx. :param tx_hash: hash of the transaction :return: Tx receipt """ try: tx_receipt = Web3Provider.get_web3().eth.waitForTransactionReceipt(tx_hash, timeout=20) except Timeout: logger.info('Waiting for transaction receipt timed out.') return except ValueError as e: logger.error(f'Waiting for transaction receipt failed: {e}') return return tx_receipt
def _load(contract_name): """Retrieve the contract instance for `contract_name` that represent the smart contract in the keeper network. :param contract_name: str name of the solidity keeper contract without the network name. :return: web3.eth.Contract instance """ assert ContractHandler.artifacts_path is not None, 'artifacts_path should be already set.' contract_definition = ContractHandler.get_contract_dict_by_name( contract_name, ContractHandler.artifacts_path) address = Web3.toChecksumAddress(contract_definition['address']) abi = contract_definition['abi'] contract = Web3Provider.get_web3().eth.contract(address=address, abi=abi) ContractHandler._contracts[contract_name] = ( contract, contract_definition['version']) return ContractHandler._contracts[contract_name]
def process_tx_receipt(tx_hash, event_instance, event_name, agreement_id=None): """ Wait until the tx receipt is processed. :param tx_hash: hash of the transaction :param event_instance: instance of ContractEvent :param event_name: name of the event to subscribe, str :param agreement_id: hex str :return: """ if not isinstance(tx_hash, bytes): raise TypeError(f'first argument should be bytes type, ' f'got type {type(tx_hash)} and value {tx_hash}') if not isinstance(event_instance, ContractEvent): raise TypeError(f'second argument should be a ContractEvent, ' f'got {event_instance} of type {type(event_instance)}') web3 = Web3Provider.get_web3() try: web3.eth.waitForTransactionReceipt(tx_hash, timeout=20) except Timeout: logger.info(f'Waiting for {event_name} transaction receipt timed out. ' f'Cannot verify receipt and event.') return False receipt = web3.eth.getTransactionReceipt(tx_hash) event_logs = event_instance.processReceipt(receipt) if receipt else None if event_logs: logger.info( f'Success: got {event_name} event after fulfilling condition.') logger.debug( f'Success: got {event_name} event after fulfilling condition. {receipt}, ' f'::: {event_logs}') else: logger.debug( f'Something is not right, cannot find the {event_name} event after calling the' f' fulfillment condition. This is the transaction receipt {receipt}' ) if receipt and receipt.status == 0: logger.warning( f'Transaction failed: tx_hash {tx_hash.hex()}, tx event {event_name}, receipt ' f'{receipt}, id {agreement_id}') return False return True
def was_derived_from(self, prov_id, new_entity_did, used_entity_did, agent_id, activity_id, account, attributes=None): tx_hash = self.send_transaction( 'wasDerivedFrom', (prov_id, new_entity_did, used_entity_did, agent_id, activity_id, attributes), transact={ 'from': account.address, 'passphrase': account.password, 'keyfile': account.key_file }) return Web3Provider.get_web3().eth.waitForTransactionReceipt( tx_hash, timeout=20)
def setup_nft_sales_agreements_environment(): consumer_acc = get_consumer_account() publisher_acc = get_publisher_account() keeper = Keeper.get_instance() ddo = get_ddo_nft_sample() did_seed = generate_prefixed_id() asset_id = keeper.did_registry.hash_did(did_seed, publisher_acc.address) ddo._did = DID.did(asset_id) keeper.did_registry.register_mintable_did( did_seed, checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id), url='http://172.17.0.1:5000', cap=10, royalties=10, account=publisher_acc, providers=None) keeper.did_registry.mint(ddo.asset_id, 10, account=publisher_acc) service_agreement = ServiceAgreement.from_ddo(ServiceTypes.NFT_SALES, ddo) agreement_id = ServiceAgreement.create_new_agreement_id() price = service_agreement.get_price() (access_cond_id, lock_cond_id, escrow_cond_id) = service_agreement.generate_agreement_condition_ids( agreement_id, asset_id, consumer_acc.address, keeper) nft_access_service_agreement = ServiceAgreement.from_ddo( ServiceTypes.NFT_ACCESS, ddo) nft_access_agreement_id = ServiceAgreement.create_new_agreement_id() (nft_access_cond_id, nft_holder_cond_id ) = nft_access_service_agreement.generate_agreement_condition_ids( nft_access_agreement_id, asset_id, consumer_acc.address, keeper) return (keeper, ddo, publisher_acc, consumer_acc, agreement_id, nft_access_agreement_id, asset_id, price, service_agreement, nft_access_service_agreement, (lock_cond_id, access_cond_id, escrow_cond_id), (nft_access_cond_id, nft_holder_cond_id))
def acted_on_behalf(self, prov_id, did, delegate_agent_id, responsible_agent_id, activity_id, signature, account, attributes=None): tx_hash = self.send_transaction( 'actedOnBehalf', (prov_id, did, delegate_agent_id, responsible_agent_id, activity_id, signature, attributes), transact={ 'from': account.address, 'passphrase': account.password, 'keyfile': account.key_file }) return Web3Provider.get_web3().eth.waitForTransactionReceipt( tx_hash, timeout=20)
def test_sign_tx(): # account_address = '0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e' account = get_publisher_account() wallet = Wallet(Web3Provider.get_web3(), account.key_file, account.password, address=account.address) tx_dict = { 'from': '0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e', 'to': '0xc354ba9AD5dF1023C2640b14A09E61a500F21546', 'gas': 153432, 'data': '0x534eb706ff3b98759dc7421dad1f42c4fbc00ceab99e4d849f884fa680398c8e65bcaf1a' '3f4b0356b3399ae841a2c6fce00787cf27dcf08e3b3e65065fea2498e621848f0000000000' '00000000000000000000000000000000000000000000000000008000000000000000000000' '000000000000000000000000000000000000000000a0000000000000000000000000000000' '00000000000000000000000000000000000000000000000000000000000000000000000000' '000000000000000000000078687474703a2f2f6c6f63616c686f73743a353030302f617069' '2f76312f61717561726975732f6173736574732f64646f2f6469643a6f703a666633623938' '37353964633734323164616431663432633466626330306365616239396534643834396638' '3834666136383033393863386536356263616631610000000000000000', 'nonce': 730, 'gasPrice': 1000000000 } Wallet._last_tx_count[account.address] = tx_dict['nonce'] - 1 tx_hash = ( '0xf901aa7d843b9aca008302575894c354ba9ad5df1023c2640b14a09e61a500f2154680b90144534eb706ff3b98759dc7421dad1f42c4fbc00ceab99e4d849f884fa680398c8e65bcaf1a3f4b0356b3399ae841a2c6fce00787cf27dcf08e3b3e65065fea2498e621848f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000078687474703a2f2f6c6f63616c686f73743a353030302f6170692f76312f61717561726975732f6173736574732f64646f2f6469643a6f703a6666336239383735396463373432316461643166343263346662633030636561623939653464383439663838346661363830333938633865363562636166316100000000000000001ba07ff531911521dd7aab8ea4a96d219033f3b80447cdf5f94a930f10806dd1f8dca006ce5047b2f91a5d895ee0680e7da9168dc8f94899f2263ef26586028613342c' ) signed_tx = wallet.sign_tx(tx_dict) assert signed_tx.hex() == tx_hash
def run_events_monitor(): setup_logging() config = get_config() keeper_url = config.keeper_url storage_path = config.get('resources', 'storage.path', fallback='./provider-events-monitor.db') web3 = Web3Provider.get_web3(keeper_url) ContractHandler.artifacts_path = get_keeper_path(config) keeper = Keeper.get_instance() init_account_envvars() account = get_account(0) if account is None: raise AssertionError( f'Provider events monitor cannot run without a valid ' f'ethereum account. Account address was not found in the environment' f'variable `PROVIDER_ADDRESS`. Please set the following environment ' f'variables and try again: `PROVIDER_ADDRESS`, [`PROVIDER_PASSWORD`, ' f'and `PROVIDER_KEYFILE` or `PROVIDER_ENCRYPTED_KEY`] or `PROVIDER_KEY`.' ) if not account.key_file and not (account.password and account.key_file): raise AssertionError( f'Provider events monitor cannot run without a valid ' f'ethereum account with either a `PROVIDER_PASSWORD` ' f'and `PROVIDER_KEYFILE`/`PROVIDER_ENCRYPTED_KEY` ' f'or private key `PROVIDER_KEY`. Current account has password {account.password}, ' f'keyfile {account.key_file}, encrypted-key {account._encrypted_key} ' f'and private-key {account._private_key}.') monitor = ProviderEventsMonitor(keeper, web3, storage_path, account) monitor.start_agreement_events_monitor() while True: time.sleep(5)