diff --git a/nucypher/blockchain/eth/actors.py b/nucypher/blockchain/eth/actors.py index 74dd128f1..09f237662 100644 --- a/nucypher/blockchain/eth/actors.py +++ b/nucypher/blockchain/eth/actors.py @@ -1749,7 +1749,7 @@ class Wallet: # Blockchain self.blockchain = BlockchainInterfaceFactory.get_interface(provider_uri) - self.__signer = signer + self.signer = signer self.__get_accounts() if client_addresses: @@ -1764,8 +1764,8 @@ class Wallet: return self.blockchain.transacting_power.account def __get_accounts(self) -> None: - if self.__signer: - signer_accounts = self.__signer.accounts + if self.signer: + signer_accounts = self.signer.accounts self.__client_accounts.extend([a for a in signer_accounts if a not in self.__client_accounts]) client_accounts = self.blockchain.client.accounts # Accounts via connected provider self.__client_accounts.extend([a for a in client_accounts if a not in self.__client_accounts]) @@ -1782,8 +1782,8 @@ class Wallet: ) -> None: if checksum_address not in self: - self.__signer = signer or Web3Signer(client=self.blockchain.client) - if isinstance(self.__signer, KeystoreSigner): + self.signer = signer or Web3Signer(client=self.blockchain.client) + if isinstance(self.signer, KeystoreSigner): raise BaseActor.ActorError(f"Staking operations are not permitted while using a local keystore signer.") self.__get_accounts() if checksum_address not in self: @@ -1791,7 +1791,7 @@ class Wallet: try: transacting_power = self.__transacting_powers[checksum_address] except KeyError: - transacting_power = TransactingPower(signer=self.__signer or Web3Signer(client=self.blockchain.client), + transacting_power = TransactingPower(signer=self.signer or Web3Signer(client=self.blockchain.client), password=password, account=checksum_address) self.__transacting_powers[checksum_address] = transacting_power diff --git a/nucypher/blockchain/eth/agents.py b/nucypher/blockchain/eth/agents.py index 5516ad2f8..e6a5a5909 100644 --- a/nucypher/blockchain/eth/agents.py +++ b/nucypher/blockchain/eth/agents.py @@ -413,7 +413,8 @@ class StakingEscrowAgent(EthereumContractAgent): if not sender_address: sender_address = staker_address contract_function: ContractFunction = self.contract.functions.deposit(staker_address, amount, lock_periods) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=sender_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=sender_address) return receipt @contract_api(TRANSACTION) @@ -428,7 +429,8 @@ class StakingEscrowAgent(EthereumContractAgent): Note that this resolved to two separate contract function signatures. """ contract_function: ContractFunction = self.contract.functions.depositAndIncrease(stake_index, amount) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) return receipt @contract_api(TRANSACTION) @@ -441,7 +443,8 @@ class StakingEscrowAgent(EthereumContractAgent): Locks tokens amount and creates new sub-stake """ contract_function: ContractFunction = self.contract.functions.lockAndCreate(amount, lock_periods) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) return receipt @contract_api(TRANSACTION) @@ -454,7 +457,8 @@ class StakingEscrowAgent(EthereumContractAgent): Locks tokens amount and add them to selected sub-stake """ contract_function: ContractFunction = self.contract.functions.lockAndIncrease(stake_index, amount) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) return receipt @contract_api(CONTRACT_CALL) @@ -562,7 +566,8 @@ class StakingEscrowAgent(EthereumContractAgent): @contract_api(TRANSACTION) def bond_worker(self, staker_address: ChecksumAddress, worker_address: ChecksumAddress) -> TxReceipt: contract_function: ContractFunction = self.contract.functions.bondWorker(worker_address) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) return receipt @contract_api(TRANSACTION) @@ -577,6 +582,7 @@ class StakingEscrowAgent(EthereumContractAgent): contract_function: ContractFunction = self.contract.functions.commitToNextPeriod() receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=worker_address, + gas_estimation_multiplier=1.5, # TODO: Workaround for #2337 fire_and_forget=fire_and_forget) return receipt @@ -588,7 +594,8 @@ class StakingEscrowAgent(EthereumContractAgent): when you intend to withdraw 100% of tokens. """ contract_function: ContractFunction = self.contract.functions.mint() - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) return receipt @contract_api(CONTRACT_CALL) @@ -649,14 +656,16 @@ class StakingEscrowAgent(EthereumContractAgent): If set to True, then all staking rewards will be automatically added to locked stake. """ contract_function: ContractFunction = self.contract.functions.setReStake(value) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) # TODO: Handle ReStakeSet event (see #1193) return receipt @contract_api(TRANSACTION) def lock_restaking(self, staker_address: ChecksumAddress, release_period: Period) -> TxReceipt: contract_function: ContractFunction = self.contract.functions.lockReStake(release_period) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) # TODO: Handle ReStakeLocked event (see #1193) return receipt @@ -678,7 +687,8 @@ class StakingEscrowAgent(EthereumContractAgent): If set to True, then stakes duration will decrease in each period with `commitToNextPeriod()`. """ contract_function: ContractFunction = self.contract.functions.setWindDown(value) - receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=staker_address) + receipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=staker_address) # TODO: Handle WindDownSet event (see #1193) return receipt @@ -1258,21 +1268,25 @@ class WorkLockAgent(EthereumContractAgent): Claim tokens - will be deposited and locked as stake in the StakingEscrow contract. """ contract_function: ContractFunction = self.contract.functions.claim() - receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=checksum_address) + receipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=checksum_address, + gas_estimation_multiplier=1.5) # FIXME return receipt @contract_api(TRANSACTION) def refund(self, checksum_address: ChecksumAddress) -> TxReceipt: """Refund ETH for completed work.""" contract_function: ContractFunction = self.contract.functions.refund() - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=checksum_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=checksum_address) return receipt @contract_api(TRANSACTION) def withdraw_compensation(self, checksum_address: ChecksumAddress) -> TxReceipt: """Withdraw compensation after force refund.""" contract_function: ContractFunction = self.contract.functions.withdrawCompensation() - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=checksum_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=checksum_address) return receipt @contract_api(CONTRACT_CALL) @@ -1574,7 +1588,8 @@ class MultiSigAgent(EthereumContractAgent): sender_address: ChecksumAddress, ) -> TxReceipt: contract_function: ContractFunction = self.contract.functions.execute(v, r, s, destination, value, data) - receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=sender_address) + receipt: TxReceipt = self.blockchain.send_transaction(contract_function=contract_function, + sender_address=sender_address) return receipt diff --git a/nucypher/blockchain/eth/interfaces.py b/nucypher/blockchain/eth/interfaces.py index 705108ccc..738ce7c95 100644 --- a/nucypher/blockchain/eth/interfaces.py +++ b/nucypher/blockchain/eth/interfaces.py @@ -15,7 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with nucypher. If not, see . """ - +import math import os import pprint import time @@ -508,9 +508,18 @@ class BlockchainInterface: contract_function: ContractFunction, sender_address: str, payload: dict = None, - transaction_gas_limit: int = None, + transaction_gas_limit: Optional[int] = None, + gas_estimation_multiplier: Optional[float] = None, ) -> dict: + # Sanity checks for the gas estimation multiplier + if gas_estimation_multiplier is not None: + if not 1 <= gas_estimation_multiplier <= 3: # TODO: Arbitrary upper bound. + raise ValueError(f"The gas estimation multiplier should be a float between 1 and 3, " + f"but we received {gas_estimation_multiplier}.") + elif transaction_gas_limit is not None: + raise ValueError("'transaction_gas_limit' and 'gas_estimation_multiplier' can't be used together.") + payload = self.build_payload(sender_address=sender_address, payload=payload, transaction_gas_limit=transaction_gas_limit) @@ -524,6 +533,16 @@ class BlockchainInterface: transaction_dict=payload, contract_function=contract_function, logger=self.log) + + # Overestimate the transaction gas limit according to the gas estimation multiplier, if any + if gas_estimation_multiplier: + gas_estimation = transaction_dict['gas'] + overestimation = int(math.ceil(gas_estimation * gas_estimation_multiplier)) + self.log.debug(f"Gas limit for this TX was increased from {gas_estimation} to {overestimation}, " + f"using a multiplier of {gas_estimation_multiplier}.") + transaction_dict['gas'] = overestimation + # TODO: What if we're going over the block limit? Not likely, but perhaps worth checking (NRN) + return transaction_dict def sign_and_broadcast_transaction(self, @@ -626,7 +645,8 @@ class BlockchainInterface: contract_function: Union[ContractFunction, ContractConstructor], sender_address: str, payload: dict = None, - transaction_gas_limit: int = None, + transaction_gas_limit: Optional[int] = None, + gas_estimation_multiplier: Optional[float] = None, confirmations: int = 0, fire_and_forget: bool = False # do not wait for receipt. ) -> dict: @@ -637,7 +657,8 @@ class BlockchainInterface: transaction = self.build_contract_transaction(contract_function=contract_function, sender_address=sender_address, payload=payload, - transaction_gas_limit=transaction_gas_limit) + transaction_gas_limit=transaction_gas_limit, + gas_estimation_multiplier=gas_estimation_multiplier) # Get transaction name try: @@ -831,7 +852,7 @@ class BlockchainDeployerInterface(BlockchainInterface): constructor_function, *constructor_args, **constructor_kwargs) - if not constructor_calldata: + if constructor_calldata: self.log.info(f"Constructor calldata: {constructor_calldata}") # diff --git a/nucypher/blockchain/eth/signers/software.py b/nucypher/blockchain/eth/signers/software.py index 1c1f00243..7f1282d0c 100644 --- a/nucypher/blockchain/eth/signers/software.py +++ b/nucypher/blockchain/eth/signers/software.py @@ -115,7 +115,7 @@ class ClefSigner(Signer): DEFAULT_CONTENT_TYPE = SIGN_DATA_FOR_ECRECOVER SIGN_DATA_CONTENT_TYPES = (SIGN_DATA_FOR_VALIDATOR, SIGN_DATA_FOR_CLIQUE, SIGN_DATA_FOR_ECRECOVER) - TIMEOUT = 60 # Default timeout for Clef of 60 seconds + TIMEOUT = 180 # Default timeout for Clef of 180 seconds def __init__(self, ipc_path: str = DEFAULT_IPC_PATH, diff --git a/nucypher/cli/commands/stake.py b/nucypher/cli/commands/stake.py index 484545c8f..9498b9a25 100644 --- a/nucypher/cli/commands/stake.py +++ b/nucypher/cli/commands/stake.py @@ -19,10 +19,12 @@ import click from web3 import Web3 +from nucypher.blockchain.eth.actors import StakeHolder from nucypher.blockchain.eth.constants import MAX_UINT16 from nucypher.blockchain.eth.events import EventRecord -from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory +from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory, BlockchainInterface from nucypher.blockchain.eth.registry import IndividualAllocationRegistry +from nucypher.blockchain.eth.signers import TrezorSigner from nucypher.blockchain.eth.signers.software import ClefSigner from nucypher.blockchain.eth.token import NU, Stake from nucypher.blockchain.eth.utils import datetime_at_period @@ -36,7 +38,7 @@ from nucypher.cli.actions.confirm import ( confirm_staged_stake, confirm_disable_snapshots ) from nucypher.cli.actions.select import select_client_account_for_staking, select_stake -from nucypher.cli.config import group_general_config +from nucypher.cli.config import group_general_config, GroupGeneralConfig from nucypher.cli.literature import ( BONDING_DETAILS, BONDING_RELEASE_INFO, @@ -126,7 +128,7 @@ class StakeHolderConfigOptions: self.registry_filepath = registry_filepath self.network = network - def create_config(self, emitter, config_file): + def retrieve_config(self, emitter, config_file): try: return StakeHolderConfiguration.from_configuration_file( emitter=emitter, @@ -200,7 +202,7 @@ class StakerOptions: self.staking_address = staking_address def create_character(self, emitter, config_file, initial_address=None, *args, **kwargs): - stakeholder_config = self.config_options.create_config(emitter, config_file) + stakeholder_config = self.config_options.retrieve_config(emitter, config_file) if initial_address is None: initial_address = self.staking_address return stakeholder_config.produce(initial_address=initial_address, *args, **kwargs) @@ -229,7 +231,7 @@ class TransactingStakerOptions: def create_character(self, emitter, config_file): opts = self.staker_options - stakeholder_config = opts.config_options.create_config(emitter, config_file) + stakeholder_config = opts.config_options.retrieve_config(emitter, config_file) # Now let's check whether we're dealing here with a regular staker or a preallocation staker is_preallocation_staker = (self.beneficiary_address and opts.staking_address) or self.allocation_filepath @@ -270,14 +272,6 @@ class TransactingStakerOptions: def get_blockchain(self): return self.staker_options.get_blockchain() - def get_password(self, blockchain, client_account): - is_clef = ClefSigner.is_valid_clef_uri(self.staker_options.config_options.signer_uri) - eth_password_needed = not self.hw_wallet and not blockchain.client.is_local and not is_clef - password = None - if eth_password_needed: - password = get_client_password(checksum_address=client_account) - return password - group_transacting_staker_options = group_options( TransactingStakerOptions, @@ -288,6 +282,18 @@ group_transacting_staker_options = group_options( ) +def get_password(stakeholder: StakeHolder, + blockchain: BlockchainInterface, + client_account: str, + hw_wallet: bool = False): + signer_handles_passwords = isinstance(stakeholder.wallet.signer, (ClefSigner, TrezorSigner)) + eth_password_needed = not hw_wallet and not blockchain.client.is_local and not signer_handles_passwords + password = None + if eth_password_needed: + password = get_client_password(checksum_address=client_account) + return password + + @click.group() def stake(): """Manage stakes and other staker-related operations.""" @@ -350,7 +356,9 @@ def accounts(general_config, staker_options, config_file): @option_force @group_general_config @option_worker_address -def bond_worker(general_config, transacting_staker_options, config_file, force, worker_address): +def bond_worker(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force, worker_address): """Bond a worker to a staker.""" emitter = setup_emitter(general_config) @@ -389,7 +397,10 @@ def bond_worker(general_config, transacting_staker_options, config_file, force, f"worker {worker_address} to staker {staking_address} " f"for a minimum of {STAKEHOLDER.economics.minimum_worker_periods} periods?", abort=True) - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.bond_worker(worker_address=worker_address) @@ -409,7 +420,9 @@ def bond_worker(general_config, transacting_staker_options, config_file, force, @option_config_file @option_force @group_general_config -def unbond_worker(general_config, transacting_staker_options, config_file, force): +def unbond_worker(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force): """ Unbond worker currently bonded to a staker. """ @@ -430,7 +443,10 @@ def unbond_worker(general_config, transacting_staker_options, config_file, force # TODO: Check preconditions (e.g., minWorkerPeriods) worker_address = STAKEHOLDER.staking_agent.get_worker_from_staker(staking_address) - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.unbond_worker() @@ -455,7 +471,9 @@ def unbond_worker(general_config, transacting_staker_options, config_file, force @option_lock_periods @group_general_config @option_from_unlocked -def create(general_config, transacting_staker_options, config_file, force, value, lock_periods, from_unlocked): +def create(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force, value, lock_periods, from_unlocked): """Initialize a new stake.""" # Setup @@ -533,7 +551,10 @@ def create(general_config, transacting_staker_options, config_file, force, value click.confirm(CONFIRM_BROADCAST_CREATE_STAKE, abort=True) # Authenticate - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) # Consistency check to prevent the above agreement from going stale. @@ -555,7 +576,9 @@ def create(general_config, transacting_staker_options, config_file, force, value @option_index @group_general_config @option_from_unlocked -def increase(general_config, transacting_staker_options, config_file, force, value, index, from_unlocked): +def increase(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force, value, index, from_unlocked): """Increase an existing stake.""" # Setup @@ -620,7 +643,10 @@ def increase(general_config, transacting_staker_options, config_file, force, val 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) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) # Execute @@ -639,7 +665,9 @@ def increase(general_config, transacting_staker_options, config_file, force, val @click.option('--lock-until', help="Period to release re-staking lock", type=click.IntRange(min=0)) @option_force @group_general_config -def restake(general_config, transacting_staker_options, config_file, enable, lock_until, force): +def restake(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, enable, lock_until, force): """Manage re-staking with --enable or --disable.""" # Setup @@ -660,7 +688,10 @@ def restake(general_config, transacting_staker_options, config_file, enable, loc confirm_enable_restaking_lock(emitter, staking_address=staking_address, release_period=lock_until) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.enable_restaking_lock(release_period=lock_until) @@ -671,7 +702,10 @@ def restake(general_config, transacting_staker_options, config_file, enable, loc confirm_enable_restaking(emitter, staking_address=staking_address) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.enable_restaking() @@ -681,7 +715,10 @@ def restake(general_config, transacting_staker_options, config_file, enable, loc click.confirm(CONFIRM_DISABLE_RESTAKING.format(staking_address=staking_address), abort=True) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.disable_restaking() @@ -696,7 +733,9 @@ def restake(general_config, transacting_staker_options, config_file, enable, loc @click.option('--enable/--disable', help="Used to enable and disable winding down", is_flag=True, default=True) @option_force @group_general_config -def winddown(general_config, transacting_staker_options, config_file, enable, force): +def winddown(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, enable, force): """Manage winding down with --enable or --disable.""" # Setup @@ -717,7 +756,10 @@ def winddown(general_config, transacting_staker_options, config_file, enable, fo confirm_enable_winding_down(emitter, staking_address=staking_address) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.enable_winding_down() @@ -727,7 +769,10 @@ def winddown(general_config, transacting_staker_options, config_file, enable, fo click.confirm(CONFIRM_DISABLE_WIND_DOWN.format(staking_address=staking_address), abort=True) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.disable_winding_down() @@ -742,7 +787,9 @@ def winddown(general_config, transacting_staker_options, config_file, enable, fo @click.option('--enable/--disable', help="Used to enable and disable taking snapshots", is_flag=True, default=True) @option_force @group_general_config -def snapshots(general_config, transacting_staker_options, config_file, enable, force): +def snapshots(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, enable, force): """Manage snapshots with --enable or --disable.""" # Setup @@ -763,7 +810,10 @@ def snapshots(general_config, transacting_staker_options, config_file, enable, f click.confirm(CONFIRM_ENABLE_SNAPSHOTS.format(staking_address=staking_address), abort=True) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.enable_snapshots() @@ -773,7 +823,10 @@ def snapshots(general_config, transacting_staker_options, config_file, enable, f confirm_disable_snapshots(emitter, staking_address=staking_address) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.disable_snapshots() @@ -790,7 +843,9 @@ def snapshots(general_config, transacting_staker_options, config_file, enable, f @option_lock_periods @option_index @group_general_config -def divide(general_config, transacting_staker_options, config_file, force, value, lock_periods, index): +def divide(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force, value, lock_periods, index): """Create a new stake from part of an existing one.""" # Setup @@ -847,7 +902,10 @@ def divide(general_config, transacting_staker_options, config_file, force, value click.confirm(CONFIRM_BROADCAST_STAKE_DIVIDE, abort=True) # Authenticate - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) # Consistency check to prevent the above agreement from going stale. @@ -874,7 +932,9 @@ def divide(general_config, transacting_staker_options, config_file, force, value @option_lock_periods @option_index @group_general_config -def prolong(general_config, transacting_staker_options, config_file, force, lock_periods, index): +def prolong(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force, lock_periods, index): """Prolong an existing stake's duration.""" # Setup @@ -916,7 +976,10 @@ def prolong(general_config, transacting_staker_options, config_file, force, lock click.confirm(CONFIRM_PROLONG.format(lock_periods=lock_periods), abort=True) # Authenticate - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) # Non-interactive: Consistency check to prevent the above agreement from going stale. @@ -941,7 +1004,9 @@ def prolong(general_config, transacting_staker_options, config_file, force, lock @group_general_config @click.option('--index-1', help="First index of stake to merge", type=click.INT) @click.option('--index-2', help="Second index of stake to merge", type=click.INT) -def merge(general_config, transacting_staker_options, config_file, force, index_1, index_2): +def merge(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force, index_1, index_2): """Merge two stakes into one.""" # Setup @@ -982,7 +1047,10 @@ def merge(general_config, transacting_staker_options, config_file, force, index_ 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) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) # Non-interactive: Consistency check to prevent the above agreement from going stale. @@ -1008,8 +1076,8 @@ def merge(general_config, transacting_staker_options, config_file, force, index_ @click.option('--withdraw-address', help="Send fee collection to an alternate address", type=EIP55_CHECKSUM_ADDRESS) @option_force @group_general_config -def collect_reward(general_config, - transacting_staker_options, +def collect_reward(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, config_file, staking_reward, policy_fee, @@ -1048,7 +1116,10 @@ def collect_reward(general_config, click.confirm(CONFIRM_COLLECTING_WITHOUT_MINTING, abort=True) # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) staking_receipt = STAKEHOLDER.collect_staking_reward() @@ -1066,7 +1137,10 @@ def collect_reward(general_config, if password is None: # Authenticate and Execute - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) policy_receipt = STAKEHOLDER.collect_policy_fee(collector_address=withdraw_address) @@ -1081,7 +1155,9 @@ def collect_reward(general_config, @option_config_file @option_force @group_general_config -def preallocation(general_config, transacting_staker_options, config_file, action, force): +def preallocation(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, action, force): """Claim token rewards collected by a preallocation contract.""" # Setup @@ -1104,7 +1180,10 @@ def preallocation(general_config, transacting_staker_options, config_file, actio force=force) # Authenticate - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(checksum_address=client_account, password=password) if action == 'withdraw': @@ -1163,7 +1242,9 @@ def events(general_config, staker_options, config_file, event_name): @option_force @group_general_config @click.option('--min-rate', help="Minimum acceptable fee rate, set by staker", type=WEI) -def set_min_rate(general_config, transacting_staker_options, config_file, force, min_rate): +def set_min_rate(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force, min_rate): """Staker sets the minimum acceptable fee rate for their associated worker.""" # Setup @@ -1184,7 +1265,10 @@ def set_min_rate(general_config, transacting_staker_options, config_file, force, min_rate = click.prompt(PROMPT_STAKER_MIN_POLICY_RATE, type=WEI) if not force: click.confirm(CONFIRM_NEW_MIN_POLICY_RATE.format(min_rate=min_rate), abort=True) - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.set_min_fee_rate(min_rate=min_rate) @@ -1202,7 +1286,9 @@ def set_min_rate(general_config, transacting_staker_options, config_file, force, @option_config_file @option_force @group_general_config -def mint(general_config, transacting_staker_options, config_file, force): +def mint(general_config: GroupGeneralConfig, + transacting_staker_options: TransactingStakerOptions, + config_file, force): """Mint last portion of reward""" # Setup @@ -1231,7 +1317,10 @@ def mint(general_config, transacting_staker_options, config_file, force): click.confirm(CONFIRM_MINTING.format(mintable_periods=mintable_periods), abort=True) # Authenticate - password = transacting_staker_options.get_password(blockchain, client_account) + password = get_password(stakeholder=STAKEHOLDER, + blockchain=blockchain, + client_account=client_account, + hw_wallet=transacting_staker_options.hw_wallet) STAKEHOLDER.assimilate(password=password) receipt = STAKEHOLDER.mint() emitter.echo(SUCCESSFUL_MINTING, color='green', verbosity=1)