diff --git a/nucypher/cli/commands/deploy.py b/nucypher/cli/commands/deploy.py index 7dbc36e0b..cc0c26fe7 100644 --- a/nucypher/cli/commands/deploy.py +++ b/nucypher/cli/commands/deploy.py @@ -50,6 +50,7 @@ from nucypher.cli.literature import ( CONFIRM_NETWORK_ACTIVATION, CONFIRM_RETARGET, CONFIRM_SELECTED_ACCOUNT, + CONFIRM_TOKEN_ALLOWANCE, CONFIRM_TOKEN_TRANSFER, CONTRACT_DEPLOYMENT_SERIES_BEGIN_ADVISORY, CONTRACT_IS_NOT_OWNABLE, @@ -529,7 +530,8 @@ def allocations(general_config, actor_options, allocation_infile, gas): @group_actor_options @option_target_address @click.option('--value', help="Amount of tokens to transfer in the smallest denomination", type=click.INT) -def transfer_tokens(general_config, actor_options, target_address, value): +@click.option('--approve', help="Approve token allowance, instead of transfer", is_flag=True, default=False) +def transfer_tokens(general_config, actor_options, target_address, value, approve): """Transfer tokens from contract's owner address to another address""" emitter = general_config.emitter @@ -544,13 +546,23 @@ def transfer_tokens(general_config, actor_options, target_address, value): stake_value_range = click.FloatRange(min=0, clamp=False) value = NU.from_tokens(click.prompt(PROMPT_TOKEN_VALUE, type=stake_value_range)) - confirmation = CONFIRM_TOKEN_TRANSFER.format(value=value, - deployer_address=deployer_address, - target_address=target_address) + value = NuNits(int(value)) + if approve: + confirmation = CONFIRM_TOKEN_ALLOWANCE.format(value=value, + deployer_address=deployer_address, + spender_address=target_address) + else: + confirmation = CONFIRM_TOKEN_TRANSFER.format(value=value, + deployer_address=deployer_address, + target_address=target_address) click.confirm(confirmation, abort=True) - receipt = token_agent.transfer(amount=NuNits(int(value)), - sender_address=deployer_address, - target_address=target_address) + + if approve: + receipt = token_agent.approve_transfer(amount=value, + sender_address=deployer_address, + spender_address=target_address) + else: + receipt = token_agent.transfer(amount=value, sender_address=deployer_address, target_address=target_address) paint_receipt_summary(emitter=emitter, receipt=receipt) diff --git a/nucypher/cli/literature.py b/nucypher/cli/literature.py index 445b30c7a..b31300aab 100644 --- a/nucypher/cli/literature.py +++ b/nucypher/cli/literature.py @@ -358,6 +358,8 @@ The staker's fee rate was set to the default value {default} such that it falls CONTRACT_IS_NOT_OWNABLE = "Contract {contract_name} is not ownable." +CONFIRM_TOKEN_ALLOWANCE = "Approve allowance of {value} from {deployer_address} to {spender_address}?" + CONFIRM_TOKEN_TRANSFER = "Transfer {value} from {deployer_address} to {target_address}?" PROMPT_TOKEN_VALUE = "Enter value in NU" diff --git a/tests/acceptance/cli/test_deploy.py b/tests/acceptance/cli/test_deploy.py index 9cb1a1e1d..47c0ca98d 100644 --- a/tests/acceptance/cli/test_deploy.py +++ b/tests/acceptance/cli/test_deploy.py @@ -128,13 +128,10 @@ def test_deploy_single_contract(click_runner, tempfile_path): assert result.exit_code == 0 -def test_transfer_tokens(click_runner, registry_filepath): - # - # Setup - # +def test_transfer_tokens(click_runner, registry_filepath, get_random_checksum_address, testerchain): # Let's transfer some NU to a random stranger - recipient_address = to_checksum_address(os.urandom(20)) + recipient_address = get_random_checksum_address() registry = LocalContractRegistry(filepath=registry_filepath) token_agent = NucypherTokenAgent(registry=registry) @@ -153,6 +150,25 @@ def test_transfer_tokens(click_runner, registry_filepath): # Check that the NU has arrived to the recipient assert token_agent.get_balance(address=recipient_address) == 42 + # Let's approve an allowance to a random spender + spender_address = get_random_checksum_address() + owner_address = testerchain.client.accounts[0] + assert token_agent.get_allowance(spender=spender_address, owner=owner_address) == 0 + + command = ['transfer-tokens', + '--target-address', spender_address, + '--value', 42, + '--approve', + '--registry-infile', registry_filepath, + '--provider', TEST_PROVIDER_URI] + + user_input = '0\n' + 'Y\n' + 'Y\n' + result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False) + assert result.exit_code == 0 + + # Check that the NU was approved for the spender + assert token_agent.get_allowance(spender=spender_address, owner=owner_address) == 42 + def test_upgrade_contracts(click_runner, registry_filepath, testerchain):