示例#1
0
def select_stake(stakeholder: StakeHolder,
                 emitter: StdoutEmitter,
                 divisible: bool = False,
                 staker_address: str = None
                 ) -> Stake:
    """Interactively select a stake or abort if there are no eligible stakes."""

    # Precondition: Active Stakes
    if staker_address:
        staker = stakeholder.get_staker(checksum_address=staker_address)
        stakes = staker.stakes
    else:
        stakes = stakeholder.all_stakes
    if not stakes:
        emitter.echo(NO_STAKES_FOUND, color='red')
        raise click.Abort

    # Precondition: Divisible Stakes
    stakes = stakeholder.sorted_stakes
    if divisible:
        emitter.echo(ONLY_DISPLAYING_DIVISIBLE_STAKES_NOTE, color='yellow')
        stakes = stakeholder.divisible_stakes
        if not stakes:
            emitter.echo(NO_DIVISIBLE_STAKES, color='red')
            raise click.Abort

    # Interactive Selection
    enumerated_stakes = dict(enumerate(stakes))
    paint_stakes(stakeholder=stakeholder, emitter=emitter, staker_address=staker_address)
    choice = click.prompt(SELECT_STAKE, type=click.IntRange(min=0, max=len(enumerated_stakes)-1))
    chosen_stake = enumerated_stakes[choice]
    return chosen_stake
示例#2
0
def select_stake(staker: Staker,
                 emitter: StdoutEmitter,
                 stakes_status: Stake.Status = Stake.Status.EDITABLE,
                 filter_function: Callable[[Stake], bool] = None) -> Stake:
    """Interactively select a stake or abort if there are no eligible stakes."""

    if stakes_status.is_child(Stake.Status.DIVISIBLE):
        emitter.echo(ONLY_DISPLAYING_DIVISIBLE_STAKES_NOTE, color='yellow')

    # Filter stakes by status
    stakes = staker.sorted_stakes(parent_status=stakes_status,
                                  filter_function=filter_function)
    if not stakes:
        emitter.echo(NO_STAKES_FOUND, color='red')
        raise click.Abort

    # Interactive Selection
    paint_unlocked = stakes_status.is_child(Stake.Status.UNLOCKED)
    paint_stakes(staker=staker,
                 emitter=emitter,
                 stakes=stakes,
                 paint_unlocked=paint_unlocked)
    indexed_stakes = {stake.index: stake for stake in stakes}
    indices = [str(index) for index in indexed_stakes.keys()]
    choice = click.prompt(SELECT_STAKE, type=click.Choice(indices))
    chosen_stake = indexed_stakes[int(choice)]
    return chosen_stake
示例#3
0
def prolong(general_config, transacting_staker_options, config_file, force, lock_periods, index):
    """Prolong an existing stake's duration."""

    # Setup
    emitter = setup_emitter(general_config)
    STAKEHOLDER = transacting_staker_options.create_character(emitter, config_file)
    action_period = STAKEHOLDER.staking_agent.get_current_period()
    blockchain = transacting_staker_options.get_blockchain()
    economics = STAKEHOLDER.economics

    # Handle account selection
    client_account, staking_address = select_client_account_for_staking(
        emitter=emitter,
        stakeholder=STAKEHOLDER,
        staking_address=transacting_staker_options.staker_options.staking_address,
        individual_allocation=STAKEHOLDER.individual_allocation,
        force=force)

    # Handle stake update and selection
    if index is not None:  # 0 is valid.
        current_stake = STAKEHOLDER.stakes[index]
    else:
        current_stake = select_stake(staker=STAKEHOLDER, emitter=emitter)

    #
    # Prolong
    #

    # Interactive
    if not lock_periods:
        max_extension = MAX_UINT16 - current_stake.final_locked_period
        # +1 because current period excluded
        min_extension = economics.minimum_locked_periods - current_stake.periods_remaining + 1
        if min_extension < 1:
            min_extension = 1
        duration_extension_range = click.IntRange(min=min_extension, max=max_extension, clamp=False)
        lock_periods = click.prompt(PROMPT_PROLONG_VALUE.format(minimum=min_extension, maximum=max_extension),
                                    type=duration_extension_range)
    if not force:
        click.confirm(CONFIRM_PROLONG.format(lock_periods=lock_periods), abort=True)

    # Authenticate
    password = transacting_staker_options.get_password(blockchain, client_account)
    STAKEHOLDER.assimilate(password=password)

    # Non-interactive: Consistency check to prevent the above agreement from going stale.
    last_second_current_period = STAKEHOLDER.staking_agent.get_current_period()
    if action_period != last_second_current_period:
        emitter.echo(PERIOD_ADVANCED_WARNING, color='red')
        raise click.Abort

    # Execute
    receipt = STAKEHOLDER.prolong_stake(stake=current_stake, additional_periods=lock_periods)

    # Report
    emitter.echo(SUCCESSFUL_STAKE_PROLONG, color='green', verbosity=1)
    paint_receipt_summary(emitter=emitter, receipt=receipt, chain_name=blockchain.client.chain_name)
    paint_stakes(emitter=emitter, staker=STAKEHOLDER)
示例#4
0
 def paintStakes(self):
     """
     Display a list of all active stakes.
     """
     if self.ursula.stakes:
         from nucypher.cli.painting.staking import paint_stakes
         paint_stakes(self.emitter, stakes=self.ursula.stakes)
     else:
         self.emitter.echo("No active stakes.")
示例#5
0
def merge(general_config, transacting_staker_options, config_file, force, index_1, index_2):
    """Merge two stakes into one."""

    # Setup
    emitter = setup_emitter(general_config)
    STAKEHOLDER = transacting_staker_options.create_character(emitter, config_file)
    action_period = STAKEHOLDER.staking_agent.get_current_period()
    blockchain = transacting_staker_options.get_blockchain()

    client_account, staking_address = select_client_account_for_staking(
        emitter=emitter,
        stakeholder=STAKEHOLDER,
        staking_address=transacting_staker_options.staker_options.staking_address,
        individual_allocation=STAKEHOLDER.individual_allocation,
        force=force)

    # Handle stakes selection
    stake_1, stake_2 = None, None

    if index_1 is not None and index_2 is not None:
        stake_1 = STAKEHOLDER.stakes[index_1]
        stake_2 = STAKEHOLDER.stakes[index_2]
    elif index_1 is not None:  # 0 is valid.
        stake_1 = STAKEHOLDER.stakes[index_1]
    elif index_2 is not None:
        stake_1 = STAKEHOLDER.stakes[index_2]

    if stake_1 is None:
        stake_1 = select_stake(staker=STAKEHOLDER, emitter=emitter)
    if stake_2 is None:
        emitter.echo(ONLY_DISPLAYING_MERGEABLE_STAKES_NOTE.format(final_period=stake_1.final_locked_period),
                     color='yellow')
        stake_2 = select_stake(staker=STAKEHOLDER,
                               emitter=emitter,
                               filter_function=lambda s: s.index != stake_1.index and
                                                         s.final_locked_period == stake_1.final_locked_period)

    if not force:
        click.confirm(CONFIRM_MERGE.format(stake_index_1=stake_1.index, stake_index_2=stake_2.index), abort=True)

    # Authenticate
    password = transacting_staker_options.get_password(blockchain, client_account)
    STAKEHOLDER.assimilate(password=password)

    # Non-interactive: Consistency check to prevent the above agreement from going stale.
    last_second_current_period = STAKEHOLDER.staking_agent.get_current_period()
    if action_period != last_second_current_period:
        emitter.echo(PERIOD_ADVANCED_WARNING, color='red')
        raise click.Abort

    # Execute
    receipt = STAKEHOLDER.merge_stakes(stake_1=stake_1, stake_2=stake_2)

    # Report
    emitter.echo(SUCCESSFUL_STAKES_MERGE, color='green', verbosity=1)
    paint_receipt_summary(emitter=emitter, receipt=receipt, chain_name=blockchain.client.chain_name)
    paint_stakes(emitter=emitter, staker=STAKEHOLDER)
示例#6
0
def stakers(general_config, registry_options, staking_address, substakes):
    """Show relevant information about stakers."""
    if substakes and not staking_address:
        raise click.BadOptionUsage(
            option_name="--substakes",
            message=
            "--substakes is only valid when used with --staking-address.")
    emitter, registry, blockchain = registry_options.setup(
        general_config=general_config)
    staking_agent = ContractAgency.get_agent(StakingEscrowAgent,
                                             registry=registry)
    stakers_list = [staking_address
                    ] if staking_address else staking_agent.get_stakers()
    paint_stakers(emitter=emitter, stakers=stakers_list, registry=registry)
    if substakes:
        staker = Staker(registry=registry,
                        domain=registry_options.network,
                        checksum_address=staking_address)
        staker.stakes.refresh()
        paint_stakes(emitter=emitter, staker=staker, paint_unlocked=True)
示例#7
0
def remove_inactive_substake(emitter, stakeholder: StakeHolder,
                             action_period: int, stake: Stake, chain_name: str,
                             force: bool) -> None:
    # Non-interactive: Consistency check to prevent the above agreement from going stale.
    last_second_current_period = stakeholder.staker.staking_agent.get_current_period(
    )
    if action_period != last_second_current_period:
        emitter.echo(PERIOD_ADVANCED_WARNING, color='red')
        raise click.Abort

    if not force:
        click.confirm(CONFIRM_REMOVE_SUBSTAKE.format(stake_index=stake.index),
                      abort=True)

    # Execute
    receipt = stakeholder.staker.remove_inactive_stake(stake=stake)

    # Report
    emitter.echo(SUCCESSFUL_STAKE_REMOVAL, color='green', verbosity=1)
    paint_receipt_summary(emitter=emitter,
                          receipt=receipt,
                          chain_name=chain_name)
    paint_stakes(emitter=emitter, staker=stakeholder.staker)
示例#8
0
文件: stake.py 项目: kkc90/nucypher
def divide(general_config, transacting_staker_options, config_file, force,
           value, lock_periods, index):
    """Create a new stake from part of an existing one."""

    # Setup
    emitter = setup_emitter(general_config)
    STAKEHOLDER = transacting_staker_options.create_character(
        emitter, config_file)
    blockchain = transacting_staker_options.get_blockchain()
    economics = STAKEHOLDER.economics
    action_period = STAKEHOLDER.staking_agent.get_current_period()

    client_account, staking_address = select_client_account_for_staking(
        emitter=emitter,
        stakeholder=STAKEHOLDER,
        staking_address=transacting_staker_options.staker_options.
        staking_address,
        individual_allocation=STAKEHOLDER.individual_allocation,
        force=force)

    # Dynamic click types (Economics)
    min_locked = economics.minimum_allowed_locked
    stake_value_range = click.FloatRange(
        min=NU.from_nunits(min_locked).to_tokens(), clamp=False)

    if transacting_staker_options.staker_options.staking_address and index is not None:  # 0 is valid.
        STAKEHOLDER.stakes = StakeList(
            registry=STAKEHOLDER.registry,
            checksum_address=transacting_staker_options.staker_options.
            staking_address)
        STAKEHOLDER.stakes.refresh()
        current_stake = STAKEHOLDER.stakes[index]
    else:
        current_stake = select_stake(stakeholder=STAKEHOLDER,
                                     emitter=emitter,
                                     divisible=True,
                                     staker_address=client_account)

    #
    # Stage Stake
    #

    # Value
    if not value:
        min_allowed_locked = NU.from_nunits(
            STAKEHOLDER.economics.minimum_allowed_locked)
        max_divide_value = max(min_allowed_locked,
                               current_stake.value - min_allowed_locked)
        prompt = PROMPT_STAKE_DIVIDE_VALUE.format(
            minimm=min_allowed_locked, maximum=str(max_divide_value))
        value = click.prompt(prompt, type=stake_value_range)
    value = NU(value, 'NU')

    # Duration
    if not lock_periods:
        max_extension = MAX_UINT16 - current_stake.final_locked_period
        divide_extension_range = click.IntRange(min=1,
                                                max=max_extension,
                                                clamp=False)
        extension = click.prompt(PROMPT_STAKE_EXTEND_VALUE,
                                 type=divide_extension_range)
    else:
        extension = lock_periods

    if not force:
        confirm_large_stake(lock_periods=extension, value=value)
        paint_staged_stake_division(emitter=emitter,
                                    stakeholder=STAKEHOLDER,
                                    original_stake=current_stake,
                                    target_value=value,
                                    extension=extension)
        click.confirm(CONFIRM_BROADCAST_STAKE_DIVIDE, abort=True)

    # Authenticate
    password = transacting_staker_options.get_password(blockchain,
                                                       client_account)

    # Consistency check to prevent the above agreement from going stale.
    last_second_current_period = STAKEHOLDER.staking_agent.get_current_period()
    if action_period != last_second_current_period:
        emitter.echo(PERIOD_ADVANCED_WARNING, red='red')
        raise click.Abort

    # Execute
    STAKEHOLDER.assimilate(checksum_address=current_stake.staker_address,
                           password=password)
    modified_stake, new_stake = STAKEHOLDER.divide_stake(
        stake_index=current_stake.index,
        target_value=value,
        additional_periods=extension)
    emitter.echo(SUCCESSFUL_STAKE_DIVIDE, color='green', verbosity=1)
    paint_receipt_summary(emitter=emitter,
                          receipt=new_stake.receipt,
                          chain_name=blockchain.client.chain_name)

    # Show the resulting stake list
    paint_stakes(emitter=emitter, stakeholder=STAKEHOLDER)
示例#9
0
文件: stake.py 项目: kkc90/nucypher
def list_stakes(general_config, staker_options, config_file, all):
    """List active stakes for current stakeholder."""
    emitter = setup_emitter(general_config)
    STAKEHOLDER = staker_options.create_character(emitter, config_file)
    paint_stakes(emitter=emitter, stakeholder=STAKEHOLDER, paint_inactive=all)
示例#10
0
def increase(general_config, transacting_staker_options, config_file, force, value, index, only_lock):
    """Increase an existing stake."""

    # Setup
    emitter = setup_emitter(general_config)
    STAKEHOLDER = transacting_staker_options.create_character(emitter, config_file)
    blockchain = transacting_staker_options.get_blockchain()

    client_account, staking_address = select_client_account_for_staking(
        emitter=emitter,
        stakeholder=STAKEHOLDER,
        staking_address=transacting_staker_options.staker_options.staking_address,
        individual_allocation=STAKEHOLDER.individual_allocation,
        force=force)

    # Handle stake update and selection
    if index is not None:  # 0 is valid.
        current_stake = STAKEHOLDER.stakes[index]
    else:
        current_stake = select_stake(staker=STAKEHOLDER, emitter=emitter)

    #
    # Stage Stake
    #

    if not value:
        if not only_lock:
            only_lock = not click.prompt(PROMPT_DEPOSIT_OR_LOCK, type=click.BOOL, default=True)

        token_balance = STAKEHOLDER.token_balance if not only_lock else STAKEHOLDER.calculate_staking_reward()
        locked_tokens = STAKEHOLDER.locked_tokens(periods=1).to_nunits()
        upper_limit = min(token_balance, NU.from_nunits(STAKEHOLDER.economics.maximum_allowed_locked - locked_tokens))

        if token_balance == 0:
            emitter.echo(INSUFFICIENT_BALANCE_TO_INCREASE, color='red')
            raise click.Abort
        if upper_limit == 0:
            emitter.echo(MAXIMUM_STAKE_REACHED, color='red')
            raise click.Abort

        stake_value_range = click.FloatRange(min=0, max=upper_limit.to_tokens(), clamp=False)
        value = click.prompt(PROMPT_STAKE_INCREASE_VALUE.format(upper_limit=upper_limit),
                             type=stake_value_range)
    value = NU.from_tokens(value)

    #
    # Review and Publish
    #

    if not force:
        lock_periods = current_stake.periods_remaining - 1
        current_period = STAKEHOLDER.staking_agent.get_current_period()
        unlock_period = current_stake.final_locked_period + 1

        confirm_large_stake(value=value, lock_periods=lock_periods)
        paint_staged_stake(emitter=emitter,
                           stakeholder=STAKEHOLDER,
                           staking_address=staking_address,
                           stake_value=value,
                           lock_periods=lock_periods,
                           start_period=current_period + 1,
                           unlock_period=unlock_period)
        click.confirm(CONFIRM_INCREASING_STAKE.format(stake_index=current_stake.index, value=value), abort=True)

    # Authenticate
    password = transacting_staker_options.get_password(blockchain, client_account)
    STAKEHOLDER.assimilate(password=password)

    # Execute
    receipt = STAKEHOLDER.increase_stake(stake=current_stake, amount=value, only_lock=only_lock)

    # Report
    emitter.echo(SUCCESSFUL_STAKE_INCREASE, color='green', verbosity=1)
    paint_receipt_summary(emitter=emitter, receipt=receipt, chain_name=blockchain.client.chain_name)
    paint_stakes(emitter=emitter, staker=STAKEHOLDER)