def events(general_config, registry_options, contract_name, from_block, to_block, event_name): """ Show events associated to NuCypher contracts """ emitter = _setup_emitter(general_config) registry = registry_options.get_registry(emitter, general_config.debug) blockchain = BlockchainInterfaceFactory.get_interface( provider_uri=registry_options.provider_uri) if not contract_name: if event_name: raise click.BadOptionUsage( option_name='--event-name', message='--event-name requires --contract-name') contract_names = [ STAKING_ESCROW_CONTRACT_NAME, POLICY_MANAGER_CONTRACT_NAME ] else: contract_names = [contract_name] if from_block is None: # Sketch of logic for getting the approximate block height of current period start, # so by default, this command only shows events of the current period last_block = blockchain.client.w3.eth.blockNumber staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) current_period = staking_agent.get_current_period() current_period_start = datetime_at_period( period=current_period, seconds_per_period=staking_agent.staking_parameters()[0], start_of_period=True) seconds_from_midnight = int( (maya.now() - current_period_start).total_seconds()) blocks_from_midnight = seconds_from_midnight // AVERAGE_BLOCK_TIME_IN_SECONDS from_block = last_block - blocks_from_midnight if to_block is None: to_block = 'latest' # TODO: additional input validation for block numbers emitter.echo(f"Showing events from block {from_block} to {to_block}") for contract_name in contract_names: title = f" {contract_name} Events ".center(40, "-") emitter.echo(f"\n{title}\n", bold=True, color='green') agent = ContractAgency.get_agent_by_contract_name( contract_name, registry) names = agent.events.names if not event_name else [event_name] for name in names: emitter.echo(f"{name}:", bold=True, color='yellow') event_method = agent.events[name] for event_record in event_method(from_block=from_block, to_block=to_block): emitter.echo(f" - {event_record}")
def events(general_config, registry_options, contract_name, from_block, to_block, event_name): """Show events associated to NuCypher contracts.""" emitter, registry, blockchain = registry_options.setup( general_config=general_config) if not contract_name: if event_name: raise click.BadOptionUsage( option_name='--event-name', message='--event-name requires --contract-name') contract_names = [ STAKING_ESCROW_CONTRACT_NAME, POLICY_MANAGER_CONTRACT_NAME ] else: contract_names = [contract_name] if from_block is None: # by default, this command only shows events of the current period last_block = blockchain.client.block_number staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) current_period = staking_agent.get_current_period() from_block = estimate_block_number_for_period( period=current_period, seconds_per_period=staking_agent.staking_parameters()[0], latest_block=last_block) if to_block is None: to_block = 'latest' # TODO: additional input validation for block numbers emitter.echo(f"Showing events from block {from_block} to {to_block}") for contract_name in contract_names: title = f" {contract_name} Events ".center(40, "-") emitter.echo(f"\n{title}\n", bold=True, color='green') agent = ContractAgency.get_agent_by_contract_name( contract_name, registry) names = agent.events.names if not event_name else [event_name] for name in names: emitter.echo(f"{name}:", bold=True, color='yellow') event_method = agent.events[name] for event_record in event_method(from_block=from_block, to_block=to_block): emitter.echo(f" - {event_record}")
def events(general_config, registry_options, contract_name, from_block, to_block, event_name, csv, csv_file, event_filters, legacy): """Show events associated with NuCypher contracts.""" if csv or csv_file: if csv and csv_file: raise click.BadOptionUsage( option_name='--event-filter', message=click.style( 'Pass either --csv or --csv-file, not both.', fg="red")) # ensure that event name is specified - different events would have different columns in the csv file if csv_file and not all((event_name, contract_name)): # TODO consider a single csv that just gets appended to for each event # - each appended event adds their column names first # - single report-type functionality, see #2561 raise click.BadOptionUsage( option_name='--csv-file, --event-name, --contract_name', message=click.style( '--event-name and --contract-name must be specified when outputting to ' 'specific file using --csv-file; alternatively use --csv', fg="red")) if not contract_name: if event_name: raise click.BadOptionUsage( option_name='--event-name', message=click.style('--event-name requires --contract-name', fg="red")) # FIXME should we force a contract name to be specified? # default to PREApplication contract contract_names = [PREApplicationAgent.contract_name] else: contract_names = [contract_name] emitter, registry, blockchain = registry_options.setup( general_config=general_config) if from_block is None: # by default, this command only shows events of the current period blocks_since_yesterday_kinda = ((60 * 60 * 24) // AVERAGE_BLOCK_TIME_IN_SECONDS) from_block = blockchain.client.block_number - blocks_since_yesterday_kinda if to_block is None: to_block = 'latest' else: # validate block range if from_block > to_block: raise click.BadOptionUsage( option_name='--to-block, --from-block', message=click.style( f'Invalid block range provided, ' f'from-block ({from_block}) > to-block ({to_block})', fg="red")) # event argument filters argument_filters = None if event_filters: try: argument_filters = parse_event_filters_into_argument_filters( event_filters) except ValueError as e: raise click.BadOptionUsage( option_name='--event-filter', message=click.style( f'Event filter must be specified as name-value pairs of ' f'the form `<name>=<value>` - {str(e)}', fg="red")) emitter.echo(f"Retrieving events from block {from_block} to {to_block}") contract_version = None if legacy and contract_name in LEGACY_CONTRACT_VERSIONS: contract_version = LEGACY_CONTRACT_VERSIONS[contract_name] for contract_name in contract_names: if legacy: versioned_contract = blockchain.get_contract_by_name( registry=registry, contract_name=contract_name, contract_version=contract_version, proxy_name='Dispatcher', use_proxy_address=True) agent = EthereumContractAgent(contract=versioned_contract) agent.contract_name = contract_name else: agent = ContractAgency.get_agent_by_contract_name( contract_name=contract_name, contract_version=contract_version, registry=registry) if event_name and event_name not in agent.events.names: raise click.BadOptionUsage( option_name='--event-name, --contract_name', message=click.style( f'{contract_name} contract does not have an event named {event_name}', fg="red")) title = f" {agent.contract_name} Events ".center(40, "-") emitter.echo(f"\n{title}\n", bold=True, color='green') names = agent.events.names if not event_name else [event_name] for name in names: # csv output file - one per (contract_name, event_name) pair csv_output_file = csv_file if csv or csv_output_file: if not csv_output_file: csv_output_file = generate_events_csv_filepath( contract_name=agent.contract_name, event_name=name) retrieve_events( emitter=emitter, agent=agent, event_name=name, # None is fine - just means all events from_block=from_block, to_block=to_block, argument_filters=argument_filters, csv_output_file=csv_output_file)
def events(general_config, registry_options, contract_name, from_block, to_block, event_name, csv, csv_file, event_filters): """Show events associated with NuCypher contracts.""" if csv or csv_file: if csv and csv_file: raise click.BadOptionUsage( option_name='--event-filter', message=f'Pass either --csv or --csv-file, not both.') # ensure that event name is specified - different events would have different columns in the csv file if csv_file and not all((event_name, contract_name)): # TODO consider a single csv that just gets appended to for each event # - each appended event adds their column names first # - single report-type functionality, see #2561 raise click.BadOptionUsage( option_name='--csv-file, --event-name, --contract_name', message= '--event-name and --contract-name must be specified when outputting to ' 'specific file using --csv-file; alternatively use --csv') if not contract_name: if event_name: raise click.BadOptionUsage( option_name='--event-name', message='--event-name requires --contract-name') # FIXME should we force a contract name to be specified? contract_names = [ STAKING_ESCROW_CONTRACT_NAME, POLICY_MANAGER_CONTRACT_NAME ] else: contract_names = [contract_name] emitter, registry, blockchain = registry_options.setup( general_config=general_config) if from_block is None: # by default, this command only shows events of the current period last_block = blockchain.client.block_number staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) current_period = staking_agent.get_current_period() from_block = estimate_block_number_for_period( period=current_period, seconds_per_period=staking_agent.staking_parameters()[1], latest_block=last_block) if to_block is None: to_block = 'latest' else: # validate block range if from_block > to_block: raise click.BadOptionUsage( option_name='--to-block, --from-block', message=f'Invalid block range provided, ' f'from-block ({from_block}) > to-block ({to_block})') # event argument filters argument_filters = None if event_filters: try: argument_filters = parse_event_filters_into_argument_filters( event_filters) except ValueError as e: raise click.BadOptionUsage( option_name='--event-filter', message=f'Event filter must be specified as name-value pairs of ' f'the form `<name>=<value>` - {str(e)}') emitter.echo(f"Retrieving events from block {from_block} to {to_block}") for contract_name in contract_names: agent = ContractAgency.get_agent_by_contract_name( contract_name, registry) if event_name and event_name not in agent.events.names: raise click.BadOptionUsage( option_name='--event-name, --contract_name', message= f'{contract_name} contract does not have an event named {event_name}' ) title = f" {agent.contract_name} Events ".center(40, "-") emitter.echo(f"\n{title}\n", bold=True, color='green') names = agent.events.names if not event_name else [event_name] for name in names: # csv output file - one per (contract_name, event_name) pair csv_output_file = csv_file if csv or csv_output_file: if not csv_output_file: csv_output_file = generate_events_csv_filepath( contract_name=agent.contract_name, event_name=name) retrieve_events( emitter=emitter, agent=agent, event_name=name, # None is fine - just means all events from_block=from_block, to_block=to_block, argument_filters=argument_filters, csv_output_file=csv_output_file)