diff --git a/newsfragments/3290.misc.rst b/newsfragments/3290.misc.rst new file mode 100644 index 000000000..62e09e335 --- /dev/null +++ b/newsfragments/3290.misc.rst @@ -0,0 +1 @@ +Add ``nucypher taco rituals`` CLI command to list ritual information for a TACo domain. diff --git a/nucypher/cli/commands/taco.py b/nucypher/cli/commands/taco.py index b1c9dbf62..2f6a4dff3 100644 --- a/nucypher/cli/commands/taco.py +++ b/nucypher/cli/commands/taco.py @@ -1,10 +1,13 @@ from pathlib import Path import click +import maya +from tabulate import tabulate from web3 import Web3 from nucypher.blockchain.eth.agents import ( ContractAgency, + CoordinatorAgent, TACoApplicationAgent, ) from nucypher.blockchain.eth.constants import ( @@ -12,6 +15,7 @@ from nucypher.blockchain.eth.constants import ( TACO_CONTRACT_NAMES, ) from nucypher.blockchain.eth.domains import TACoDomain +from nucypher.blockchain.eth.utils import truncate_checksum_address from nucypher.cli.config import group_general_config from nucypher.cli.options import ( group_options, @@ -106,6 +110,16 @@ option_to_block = click.option( type=click.INT, ) +option_ritual_ids = click.option( + "--ritual-id", + "-r", + "ritual_ids", + help="ID of a ritual", + multiple=True, + type=click.INT, + default=[], +) + @click.group() def taco(): @@ -116,7 +130,7 @@ def taco(): @group_registry_options @group_general_config def application_info(general_config, registry_options): - """Overall information for the TACo Application.""" + """Overall information about the TACo Application.""" emitter, registry, blockchain_endpoint = registry_options.setup( general_config=general_config ) @@ -129,7 +143,7 @@ def application_info(general_config, registry_options): @group_registry_options @group_general_config def active_providers(general_config, registry_options): - """List of active stakers for the TACo Application""" + """List of active stakers for the TACo Domain.""" emitter, registry, blockchain_endpoint = registry_options.setup( general_config=general_config ) @@ -148,6 +162,80 @@ def active_providers(general_config, registry_options): emitter.echo(f"\t{provider} ..... {Web3.from_wei(staked, 'ether'):,}") +@taco.command() +@option_ritual_ids +@click.option( + "--show-inactive", + "-i", + "show_inactive", + help="Include failed/expired rituals", + is_flag=True, +) +@group_registry_options +@group_general_config +def rituals(ritual_ids, show_inactive, registry_options, general_config): + """Information about rituals on the TACo domain.""" + if not show_inactive and ritual_ids: + # provided ritual ids may/may not be active + show_inactive = True + + emitter, registry, blockchain_endpoint = registry_options.setup( + general_config=general_config + ) + coordinator_agent = ContractAgency.get_agent( + CoordinatorAgent, registry=registry, blockchain_endpoint=blockchain_endpoint + ) + + headers = [ + "ID", + "Authority", + "AccessController", + "Threshold", + "Participants", + "Expiry", + "State", + "Active", + ] + + now = maya.now() + rows = list() + ritual_id_list = ( + ritual_ids if ritual_ids else range(coordinator_agent.number_of_rituals()) + ) + for ritual_id in ritual_id_list: + ritual = coordinator_agent.get_ritual(ritual_id) + + ritual_status = coordinator_agent.get_ritual_status(ritual_id=ritual_id) + ritual_expiry = maya.MayaDT(epoch=ritual.end_timestamp) + is_ritual_active = all( + [ + ritual_status == CoordinatorAgent.Ritual.Status.FINALIZED, + ritual_expiry > now, + ] + ) + if not show_inactive and not is_ritual_active: + continue + + row = [ + ritual_id, + truncate_checksum_address(ritual.authority), + truncate_checksum_address(ritual.access_controller), + f"{ritual.threshold}/{ritual.dkg_size}", + "\n".join( + [truncate_checksum_address(p.provider) for p in ritual.participants] + ), + ritual_expiry.rfc3339(), + ritual_status, + "✓" if is_ritual_active else "x", + ] + + rows.append(row) + + emitter.echo( + tabulate(rows, headers=headers, showindex=False, tablefmt="fancy_grid") + ) + + @taco.command() @group_registry_options @group_general_config