diff --git a/neo/Prompt/CommandBase.py b/neo/Prompt/CommandBase.py index b4dbce1c3..8cf8c1d09 100644 --- a/neo/Prompt/CommandBase.py +++ b/neo/Prompt/CommandBase.py @@ -67,7 +67,7 @@ def command_desc(self): # Raise KeyError exception if the command does not exist def execute_sub_command(self, id, arguments): - self.__sub_commands[id].execute(arguments) + return self.__sub_commands[id].execute(arguments) def register_sub_command(self, sub_command, additional_ids=[]): """ diff --git a/neo/Prompt/Commands/Send.py b/neo/Prompt/Commands/Send.py index 6ca449e00..1695bb2bb 100755 --- a/neo/Prompt/Commands/Send.py +++ b/neo/Prompt/Commands/Send.py @@ -13,16 +13,77 @@ import json from prompt_toolkit import prompt import traceback +from neo.Prompt.PromptData import PromptData +from neo.Prompt.CommandBase import CommandBase, CommandDesc, ParameterDesc from logzero import logger +class CommandWalletSend(CommandBase): + + def __init__(self): + super().__init__() + + def execute(self, arguments): + framework = construct_send_basic(PromptData.Wallet, arguments) + if type(framework) is list: + return process_transaction(PromptData.Wallet, contract_tx=framework[0], scripthash_from=framework[1], + fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + return framework + + def command_desc(self): + p1 = ParameterDesc('assetId or name', 'the asset you wish to send') + p2 = ParameterDesc('address', 'the NEO address you will send to') + p3 = ParameterDesc('amount', 'the amount of the asset you wish to send') + p4 = ParameterDesc('--from-addr={addr}', 'specify the NEO address you wish to send from', optional=True) + p5 = ParameterDesc('--fee={priority_fee}', 'attach a fee to give your tx priority (> 0.001)', optional=True) + p6 = ParameterDesc('--owners=[{addr}, ...]', 'specify tx owners', optional=True) + p7 = ParameterDesc('--tx-attr=[{"usage": ,"data":""}, ...]', 'specify unique tx attributes', optional=True) + params = [p1, p2, p3, p4, p5, p6, p7] + return CommandDesc('send', 'send an asset', params=params) + + +class CommandWalletSendMany(CommandBase): + + def __init__(self): + super().__init__() + + def execute(self, arguments): + framework = construct_send_many(PromptData.Wallet, arguments) + if type(framework) is list: + return process_transaction(PromptData.Wallet, contract_tx=framework[0], scripthash_from=framework[1], scripthash_change=framework[2], + fee=framework[3], owners=framework[4], user_tx_attributes=framework[5]) + return framework + + def command_desc(self): + p1 = ParameterDesc('number of outgoing tx', 'the number of tx you wish to send') + p2 = ParameterDesc('--change-addr={addr}', 'specify the change address', optional=True) + p3 = ParameterDesc('--from-addr={addr}', 'specify the NEO address you wish to send from', optional=True) + p4 = ParameterDesc('--fee={priority_fee}', 'attach a fee to give your tx priority (> 0.001)', optional=True) + p5 = ParameterDesc('--owners=[{addr}, ...]', 'specify tx owners', optional=True) + p6 = ParameterDesc('--tx-attr=[{"usage": ,"data":""}, ...]', 'specify unique tx attributes', optional=True) + params = [p1, p2, p3, p4, p5, p6] + return CommandDesc('sendmany', 'send multiple contract transactions', params=params) + + +class CommandWalletSign(CommandBase): + + def __init__(self): + super().__init__() + + def execute(self, arguments): + jsn = get_arg(arguments) + return parse_and_sign(PromptData.Wallet, jsn) + + def command_desc(self): + p1 = ParameterDesc('jsn', 'transaction in JSON format') + params = [p1] + return CommandDesc('sign', 'sign multi-sig tx', params=params) + + def construct_send_basic(wallet, arguments): - if not wallet: - print("please open a wallet") - return False if len(arguments) < 3: print("Not enough arguments") - return False + return arguments, from_address = get_from_addr(arguments) arguments, priority_fee = get_fee(arguments) @@ -35,39 +96,40 @@ def construct_send_basic(wallet, arguments): assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") - return False + return scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: logger.debug("invalid address") - return False + return scripthash_from = None if from_address is not None: scripthash_from = lookup_addr_str(wallet, from_address) if scripthash_from is None: logger.debug("invalid address") - return False + return # if this is a token, we will use a different # transfer mechanism if type(assetId) is NEP5Token: - return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), tx_attributes=user_tx_attributes) + return do_token_transfer(assetId, wallet, from_address, address_to, amount_from_string(assetId, amount), + tx_attributes=user_tx_attributes) f8amount = get_asset_amount(amount, assetId) if f8amount is False: logger.debug("invalid amount") - return False + return if float(amount) == 0: print("amount cannot be 0") - return False + return fee = Fixed8.Zero() if priority_fee is not None: fee = priority_fee if fee is False: logger.debug("invalid fee") - return False + return output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) contract_tx = ContractTransaction(outputs=[output]) @@ -75,20 +137,17 @@ def construct_send_basic(wallet, arguments): def construct_send_many(wallet, arguments): - if not wallet: - print("please open a wallet") - return False if len(arguments) is 0: print("Not enough arguments") - return False + return outgoing = get_arg(arguments, convert_to_int=True) if outgoing is None: print("invalid outgoing number") - return False + return if outgoing < 1: print("outgoing number must be >= 1") - return False + return arguments, from_address = get_from_addr(arguments) arguments, change_address = get_change_addr(arguments) @@ -103,23 +162,23 @@ def construct_send_many(wallet, arguments): assetId = get_asset_id(wallet, to_send) if assetId is None: print("Asset id not found") - return False + return if type(assetId) is NEP5Token: print('Sendmany does not support NEP5 tokens') - return False + return address_to = prompt("Address to: ") scripthash_to = lookup_addr_str(wallet, address_to) if scripthash_to is None: logger.debug("invalid address") - return False + return amount = prompt("Amount to send: ") f8amount = get_asset_amount(amount, assetId) if f8amount is False: logger.debug("invalid amount") - return False + return if float(amount) == 0: print("amount cannot be 0") - return False + return tx_output = TransactionOutput(AssetId=assetId, Value=f8amount, script_hash=scripthash_to) output.append(tx_output) contract_tx = ContractTransaction(outputs=output) @@ -130,7 +189,7 @@ def construct_send_many(wallet, arguments): scripthash_from = lookup_addr_str(wallet, from_address) if scripthash_from is None: logger.debug("invalid address") - return False + return scripthash_change = None @@ -138,14 +197,14 @@ def construct_send_many(wallet, arguments): scripthash_change = lookup_addr_str(wallet, change_address) if scripthash_change is None: logger.debug("invalid address") - return False + return fee = Fixed8.Zero() if priority_fee is not None: fee = priority_fee if fee is False: logger.debug("invalid fee") - return False + return print("sending with fee: %s " % fee.ToString()) return [contract_tx, scripthash_from, scripthash_change, fee, owners, user_tx_attributes] @@ -160,13 +219,13 @@ def process_transaction(wallet, contract_tx, scripthash_from=None, scripthash_ch if tx is None: logger.debug("insufficient funds") - return False + return # password prompt passwd = prompt("[Password]> ", is_password=True) if not wallet.ValidatePassword(passwd): print("incorrect password") - return False + return standard_contract = wallet.GetStandardAddress() @@ -216,14 +275,14 @@ def process_transaction(wallet, contract_tx, scripthash_from=None, scripthash_ch else: print("Transaction initiated, but the signature is incomplete") print(json.dumps(context.ToJson(), separators=(',', ':'))) - return False + return except Exception as e: print("could not send: %s " % e) traceback.print_stack() traceback.print_exc() - return False + return def parse_and_sign(wallet, jsn): diff --git a/neo/Prompt/Commands/Wallet.py b/neo/Prompt/Commands/Wallet.py index 788a5163e..ef517384d 100644 --- a/neo/Prompt/Commands/Wallet.py +++ b/neo/Prompt/Commands/Wallet.py @@ -19,6 +19,7 @@ from neo.Implementations.Wallets.peewee.Models import Account from neo.Prompt.CommandBase import CommandBase, CommandDesc, ParameterDesc from neo.Prompt.PromptData import PromptData +from neo.Prompt.Commands.Send import CommandWalletSend, CommandWalletSendMany, CommandWalletSign from neo.logging import log_manager @@ -30,9 +31,14 @@ def __init__(self): super().__init__() self.register_sub_command(CommandWalletCreate()) + self.register_sub_command(CommandWalletOpen()) + self.register_sub_command(CommandWalletClose()) self.register_sub_command(CommandWalletVerbose(), ['v', '--v']) self.register_sub_command(CommandWalletMigrate()) self.register_sub_command(CommandWalletCreateAddress()) + self.register_sub_command(CommandWalletSend()) + self.register_sub_command(CommandWalletSendMany()) + self.register_sub_command(CommandWalletSign()) def command_desc(self): return CommandDesc('wallet', 'manage wallets') @@ -42,9 +48,8 @@ def execute(self, arguments): item = get_arg(arguments) # Create and Open must be handled specially. - if item == 'create': - self.execute_sub_command(item, arguments[1:]) - return + if item in {'create', 'open'}: + return self.execute_sub_command(item, arguments[1:]) if not wallet: print("Please open a wallet") @@ -55,9 +60,10 @@ def execute(self, arguments): return try: - self.execute_sub_command(item, arguments[1:]) + return self.execute_sub_command(item, arguments[1:]) except KeyError: print(f"Wallet: {item} is an invalid parameter") + return class CommandWalletCreate(CommandBase): @@ -66,6 +72,8 @@ def __init__(self): super().__init__() def execute(self, arguments): + if PromptData.Wallet: + PromptData.close_wallet() path = get_arg(arguments, 0) if path: @@ -88,6 +96,7 @@ def execute(self, arguments): key = PromptData.Wallet.GetKey(contract.PublicKeyHash) print("Wallet %s" % json.dumps(PromptData.Wallet.ToJson(), indent=4)) print("Pubkey %s" % key.PublicKey.encode_point(True)) + return PromptData.Wallet except Exception as e: print("Exception creating wallet: %s" % e) PromptData.Wallet = None @@ -100,15 +109,68 @@ def execute(self, arguments): if PromptData.Wallet: PromptData.Prompt.start_wallet_loop() + return else: print("Please specify a path") + return def command_desc(self): p1 = ParameterDesc('path', 'path to store the wallet file') return CommandDesc('create', 'creates a new NEO wallet address', [p1]) +class CommandWalletOpen(CommandBase): + + def __init__(self): + super().__init__() + + def execute(self, arguments): + if PromptData.Wallet: + PromptData.close_wallet() + + path = get_arg(arguments, 0) + + if path: + + if not os.path.exists(path): + print("Wallet file not found") + return + + passwd = prompt("[password]> ", is_password=True) + password_key = to_aes_key(passwd) + + try: + PromptData.Wallet = UserWallet.Open(path, password_key) + + PromptData.Prompt.start_wallet_loop() + print("Opened wallet at %s" % path) + return PromptData.Wallet + except Exception as e: + print("Could not open wallet: %s" % e) + return + + else: + print("Please specify a path") + return + + def command_desc(self): + p1 = ParameterDesc('path', 'path to open the wallet file') + return CommandDesc('open', 'opens a NEO wallet', [p1]) + + +class CommandWalletClose(CommandBase): + + def __init__(self): + super().__init__() + + def execute(self, arguments=None): + return PromptData.close_wallet() + + def command_desc(self): + return CommandDesc('close', 'closes the open NEO wallet') + + class CommandWalletVerbose(CommandBase): def __init__(self): @@ -116,6 +178,7 @@ def __init__(self): def execute(self, arguments): print("Wallet %s " % json.dumps(PromptData.Wallet.ToJson(verbose=True), indent=4)) + return True def command_desc(self): return CommandDesc('verbose', 'show additional wallet details') @@ -130,6 +193,8 @@ def execute(self, arguments): if PromptData.Wallet is not None: PromptData.Wallet.Migrate() print("Migrated wallet") + return True + return False def command_desc(self): p1 = ParameterDesc('option1', 'description of params 1') @@ -146,7 +211,7 @@ def __init__(self): def execute(self, arguments): addresses_to_create = get_arg(arguments, 0) - CreateAddress(PromptData.Wallet, addresses_to_create) + return CreateAddress(PromptData.Wallet, addresses_to_create) def command_desc(self): return CommandDesc('create_addr', 'create a wallet address') diff --git a/neo/Prompt/Commands/tests/test_send_command.py b/neo/Prompt/Commands/tests/test_send_command.py index 3721f036a..0e1c349f4 100644 --- a/neo/Prompt/Commands/tests/test_send_command.py +++ b/neo/Prompt/Commands/tests/test_send_command.py @@ -3,15 +3,14 @@ from neo.Implementations.Wallets.peewee.UserWallet import UserWallet from neo.Core.Blockchain import Blockchain from neocore.UInt160 import UInt160 -from neo.Prompt.Commands.Send import construct_send_basic, construct_send_many, process_transaction from neo.Prompt.Commands.Wallet import ImportToken from neo.Prompt.Utils import get_tx_attr_from_args -from neo.Prompt.Commands import Send +from neo.Prompt.Commands import Send, Wallet +from neo.Prompt.PromptData import PromptData import shutil -from mock import MagicMock -import json - from mock import patch +import json +from io import StringIO class UserWalletTestCase(WalletFixtureTestCase): @@ -39,35 +38,34 @@ def GetWallet1(cls, recreate=False): to_aes_key(UserWalletTestCase.wallet_1_pass())) return cls._wallet1 + @classmethod + def tearDown(cls): + PromptData.Wallet = None + def test_send_neo(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '50'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '50'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) - def test_send_gas_mimic_prompt(self): + def test_send_gas(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '5'] - res = False + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '5'] - framework = construct_send_basic(wallet, args) - if type(framework) is list: - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) def test_send_with_fee_and_from_addr(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '1', '--from-addr=AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3', '--fee=0.005'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '1', '--from-addr=AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3', '--fee=0.005'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) # verify successful tx @@ -77,193 +75,186 @@ def test_send_with_fee_and_from_addr(self): self.assertEqual(json_res['net_fee'], "0.005") # verify correct fee def test_send_no_wallet(self): + with patch('sys.stdout', new=StringIO()) as mock_print: + args = ["send", "neo", self.wallet_1_addr, '5'] - wallet = None - args = ['neo', self.watch_addr_str, '50'] + Wallet.CommandWallet().execute(args) - framework = construct_send_basic(wallet, args) - - self.assertFalse(framework) + self.assertIn("Please open a wallet", mock_print.getvalue()) def test_send_bad_args(self): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str] # too few args + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str] # too few args - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_bad_assetid(self): - wallet = self.GetWallet1(recreate=True) - args = ['blah', self.watch_addr_str, '12'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'blah', self.watch_addr_str, '12'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_bad_address_to(self): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) address_to = 'AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkE' # address_to is too short causing ToScriptHash to fail - args = ['neo', address_to, '12'] + args = ['send', 'neo', address_to, '12'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_bad_address_from(self): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) address_from = '--from-addr=AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc' # address_from is too short causing ToScriptHash to fail - args = ['neo', self.watch_addr_str, '12', address_from] + args = ['send', 'neo', self.watch_addr_str, '12', address_from] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_negative_amount(self): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '-12'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '-12'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_zero_amount(self): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '0'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '0'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_weird_amount(self): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '12.abc3'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '12.abc3'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_bad_precision_amount(self): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '12.01'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '12.01'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_negative_fee(self): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '12', '--fee=-0.005'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '12', '--fee=-0.005'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_weird_fee(self): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '12', '--fee=0.0abc'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '12', '--fee=0.0abc'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_token_bad(self): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) token_hash = 'f8d448b227991cf07cb96a6f9c0322437f1599b9' - ImportToken(wallet, token_hash) + ImportToken(PromptData.Wallet, token_hash) - args = ['NEP5', self.watch_addr_str, '32'] + args = ['send', 'NEP5', self.watch_addr_str, '32'] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_send_token_ok(self): with patch('neo.Prompt.Commands.Tokens.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) token_hash = '31730cc9a1844891a3bafd1aa929a4142860d8d3' - ImportToken(wallet, token_hash) + ImportToken(PromptData.Wallet, token_hash) - args = ['NXT4', self.watch_addr_str, '30', '--from-addr=%s' % self.wallet_1_addr] + args = ['send', 'NXT4', self.watch_addr_str, '30', '--from-addr=%s' % self.wallet_1_addr] - framework = construct_send_basic(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertTrue(framework) + self.assertTrue(res) def test_insufficient_funds(self): - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '72620'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '72620'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertFalse(res) def test_bad_password(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=['blah']): - wallet = self.GetWallet1(recreate=True) - args = ['neo', self.watch_addr_str, '50'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'neo', self.watch_addr_str, '50'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertFalse(res) @patch.object(Send, 'gather_signatures') def test_owners(self, mock): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) - args = ['gas', self.wallet_1_addr, '2', "--owners=['AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK','APRgMZHZubii29UXF9uFa6sohrsYupNAvx']"] + args = ['send', 'gas', self.wallet_1_addr, '2', "--owners=['AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK','APRgMZHZubii29UXF9uFa6sohrsYupNAvx']"] - framework = construct_send_basic(wallet, args) - process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + Wallet.CommandWallet().execute(args) self.assertTrue(mock.called) def test_attributes(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '2', '--tx-attr={"usage":241,"data":"This is a remark"}'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '2', '--tx-attr={"usage":241,"data":"This is a remark"}'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) self.assertEqual(2, len(res.Attributes)) # By default the script_hash of the transaction sender is added to the TransactionAttribute list, therefore the Attributes length is `count` + 1 def test_multiple_attributes(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '2', '--tx-attr=[{"usage":241,"data":"This is a remark"},{"usage":242,"data":"This is a remark 2"}]'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '2', '--tx-attr=[{"usage":241,"data":"This is a remark"},{"usage":242,"data":"This is a remark 2"}]'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) self.assertEqual(3, len(res.Attributes)) def test_bad_attributes(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '2', '--tx-attr=[{"usa:241"data":his is a remark"}]'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '2', '--tx-attr=[{"usa:241"data":his is a remark"}]'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) self.assertEqual(1, len(res.Attributes)) @@ -292,54 +283,43 @@ def test_utilst_bad_type(self): def test_fails_to_sign_tx(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): with patch('neo.Wallets.Wallet.Wallet.Sign', return_value=False): - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '2'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertFalse(res) def test_fails_to_relay_tx(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]): with patch('neo.Prompt.Commands.Send.NodeLeader.Relay', return_value=False): - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '2'] - framework = construct_send_basic(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], fee=framework[2], owners=framework[3], user_tx_attributes=framework[4]) + res = Wallet.CommandWallet().execute(args) self.assertFalse(res) - @patch('neo.Prompt.Commands.Send.traceback') - def test_could_not_send(self, mocked_tracback_module): + def test_could_not_send(self): # mocking traceback module to avoid stacktrace printing during test run + with patch('neo.Prompt.Commands.Send.traceback'): + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['send', 'gas', self.watch_addr_str, '2'] - wallet = self.GetWallet1(recreate=True) - args = ['gas', self.watch_addr_str, '2'] - - contract_tx, scripthash_from, fee, owners, user_tx_attributes = construct_send_basic(wallet, args) - scripthash_change = scripthash_from - # mocking wallet to trigger the exception - wallet = MagicMock() - wallet.MakeTransaction.side_effect = Exception - res = process_transaction(wallet, contract_tx, scripthash_from, scripthash_change, fee, owners, user_tx_attributes) # forces the 'try:' to fail + with patch('neo.Wallets.Wallet.Wallet.MakeTransaction', side_effect=[Exception]): + res = Wallet.CommandWallet().execute(args) - self.assertFalse(res) + self.assertFalse(res) def test_sendmany_good_simple(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "1", UserWalletTestCase.wallet_1_pass()]): + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2'] - wallet = self.GetWallet1(recreate=True) - args = ["2"] - - framework = construct_send_many(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], scripthash_change=framework[2], fee=framework[3], owners=framework[4], user_tx_attributes=framework[5]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) # verify successful tx - json_res = res.ToJson() - self.assertEqual(self.watch_addr_str, json_res['vout'][0]['address']) # verify correct address_to # check for 2 transfers transfers = 0 @@ -350,16 +330,15 @@ def test_sendmany_good_simple(self): def test_sendmany_good_complex(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", "AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK", "1", "gas", "AXjaFSP23Jkbe6Pk9pPGT6NBDs1HVdqaXK", "1", UserWalletTestCase.wallet_1_pass()]): - wallet = self.GetWallet1(recreate=True) - args = ["2", '--from-addr=%s' % self.wallet_1_addr, '--change-addr=%s' % self.watch_addr_str, '--fee=0.005'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2', '--from-addr=%s' % self.wallet_1_addr, '--change-addr=%s' % self.watch_addr_str, '--fee=0.005'] address_from_account_state = Blockchain.Default().GetAccountState(self.wallet_1_addr).ToJson() address_from_gas = next(filter(lambda b: b['asset'] == '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7', address_from_account_state['balances'])) address_from_gas_bal = address_from_gas['value'] - framework = construct_send_many(wallet, args) - res = process_transaction(wallet, contract_tx=framework[0], scripthash_from=framework[1], scripthash_change=framework[2], fee=framework[3], owners=framework[4], user_tx_attributes=framework[5]) + res = Wallet.CommandWallet().execute(args) self.assertTrue(res) # verify successful tx @@ -370,134 +349,133 @@ def test_sendmany_good_complex(self): self.assertEqual('0.005', json_res['net_fee']) def test_sendmany_no_wallet(self): + with patch('sys.stdout', new=StringIO()) as mock_print: + args = ['sendmany', '2'] - wallet = None - args = ['2'] + Wallet.CommandWallet().execute(args) - framework = construct_send_many(wallet, args) - - self.assertFalse(framework) + self.assertIn("Please open a wallet", mock_print.getvalue()) def test_sendmany_bad_args(self): - wallet = self.GetWallet1(recreate=True) - args = [] # too few args + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany'] # too few args - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_bad_outgoing(self): - wallet = self.GetWallet1(recreate=True) - args = ['0'] # too few outgoing + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '0'] # too few outgoing - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_weird_outgoing(self): - wallet = self.GetWallet1(recreate=True) - args = ['0.5'] # weird number outgoing + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '0.5'] # weird number outgoing - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_bad_assetid(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "blah", self.watch_addr_str, "1"]): - wallet = self.GetWallet1(recreate=True) - args = ['2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2'] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_token(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "NXT4", self.watch_addr_str, "32"]): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) token_hash = '31730cc9a1844891a3bafd1aa929a4142860d8d3' - ImportToken(wallet, token_hash) + ImportToken(PromptData.Wallet, token_hash) - args = ["2", '--from-addr=%s' % self.wallet_1_addr] + args = ['sendmany', "2", '--from-addr=%s' % self.wallet_1_addr] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_bad_address_to(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", "AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkE", "1"]): # address is too short - wallet = self.GetWallet1(recreate=True) - args = ['2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2'] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_negative_amount(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "-1"]): - wallet = self.GetWallet1(recreate=True) - args = ['2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2'] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_zero_amount(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "0"]): - wallet = self.GetWallet1(recreate=True) - args = ['2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2'] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_weird_amount(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "5.abc3"]): - wallet = self.GetWallet1(recreate=True) - args = ['2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2'] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_bad_precision_amount(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["gas", self.watch_addr_str, "1", "neo", self.watch_addr_str, "5.01"]): - wallet = self.GetWallet1(recreate=True) - args = ['2'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2'] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_bad_address_from(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "1"]): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) address_from = '--from-addr=AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc' # address_from is too short causing ToScriptHash to fail - args = ['2', address_from] + args = ['sendmany', '2', address_from] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_bad_change_address(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "1"]): - wallet = self.GetWallet1(recreate=True) + PromptData.Wallet = self.GetWallet1(recreate=True) change_address = '--change-addr=AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkE' # change address is too short causing ToScriptHash to fail - args = ['2', change_address] + args = ['sendmany', '2', change_address] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) def test_sendmany_negative_fee(self): with patch('neo.Prompt.Commands.Send.prompt', side_effect=["neo", self.watch_addr_str, "1", "gas", self.watch_addr_str, "1"]): - wallet = self.GetWallet1(recreate=True) - args = ['2', '--fee=-0.005'] + PromptData.Wallet = self.GetWallet1(recreate=True) + args = ['sendmany', '2', '--fee=-0.005'] - framework = construct_send_many(wallet, args) + res = Wallet.CommandWallet().execute(args) - self.assertFalse(framework) + self.assertFalse(res) diff --git a/neo/Prompt/Commands/tests/test_wallet_commands.py b/neo/Prompt/Commands/tests/test_wallet_commands.py index c9ed30d19..10068ec79 100644 --- a/neo/Prompt/Commands/tests/test_wallet_commands.py +++ b/neo/Prompt/Commands/tests/test_wallet_commands.py @@ -4,8 +4,9 @@ from neo.Core.Blockchain import Blockchain from neocore.UInt160 import UInt160 from neocore.Fixed8 import Fixed8 -from neo.Prompt.Commands.Wallet import CreateAddress, DeleteAddress, ImportToken, ImportWatchAddr, ShowUnspentCoins, SplitUnspentCoin +from neo.Prompt.Commands.Wallet import CommandWallet, CreateAddress, DeleteAddress, ImportToken, ImportWatchAddr, ShowUnspentCoins, SplitUnspentCoin import shutil +from mock import patch class UserWalletTestCase(WalletFixtureTestCase): @@ -33,6 +34,67 @@ def GetWallet1(cls, recreate=False): to_aes_key(UserWalletTestCase.wallet_1_pass())) return cls._wallet1 + # Beginning with refactored tests + + def test_wallet_open(self): + with patch('neo.Prompt.PromptData.PromptData.Prompt'): + with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=["testpassword"]): + # test wallet open successful + args = ['open', 'fixtures/testwallet.db3'] + + res = CommandWallet().execute(args) + + self.assertEqual(str(type(res)), "") + + # test wallet open with no path; this will also close the open wallet + args = ['open'] + + res = CommandWallet().execute(args) + + self.assertFalse(res) + + # test wallet open with bad path + args = ['open', 'badpath'] + + res = CommandWallet().execute(args) + + self.assertFalse(res) + + # test wallet open unsuccessful + with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=["testpassword"]): + with patch('neo.Implementations.Wallets.peewee.UserWallet.UserWallet.Open', side_effect=[Exception('test exception')]): + args = ['open', 'fixtures/testwallet.db3'] + + res = CommandWallet().execute(args) + + self.assertFalse(res) + + def test_wallet_close(self): + with patch('neo.Prompt.PromptData.PromptData.Prompt'): + # test wallet close with no wallet + args = ['close'] + + res = CommandWallet().execute(args) + + self.assertFalse(res) + + # test wallet close with open wallet + with patch('neo.Prompt.Commands.Wallet.prompt', side_effect=["testpassword"]): + args = ['open', 'fixtures/testwallet.db3'] + + res = CommandWallet().execute(args) + + self.assertEqual(str(type(res)), "") + + # now close the open wallet manually + args = ['close'] + + res = CommandWallet().execute(args) + + self.assertTrue(res) + + ########################################################## + ########################################################## def test_1_import_addr(self): wallet = self.GetWallet1(recreate=True) diff --git a/neo/Prompt/PromptData.py b/neo/Prompt/PromptData.py index 0493676e2..2bb5a6cdc 100644 --- a/neo/Prompt/PromptData.py +++ b/neo/Prompt/PromptData.py @@ -1,3 +1,15 @@ class PromptData: Prompt = None Wallet = None + + @staticmethod + def close_wallet(): + if not PromptData.Wallet: + return False + + path = PromptData.Wallet._path + PromptData.Prompt.stop_wallet_loop() + PromptData.Wallet.Close() + PromptData.Wallet = None + print("Closed wallet %s" % path) + return True diff --git a/neo/bin/prompt.py b/neo/bin/prompt.py index 91935eac3..53fc3a2e6 100755 --- a/neo/bin/prompt.py +++ b/neo/bin/prompt.py @@ -30,7 +30,7 @@ from neo.Prompt.Commands.Invoke import InvokeContract, TestInvokeContract, test_invoke from neo.Prompt.Commands.LoadSmartContract import LoadContract, GatherContractDetails, ImportContractAddr, \ ImportMultiSigContractAddr -from neo.Prompt.Commands.Send import construct_send_basic, construct_send_many, process_transaction, parse_and_sign +# from neo.Prompt.Commands.Send import construct_send_basic, construct_send_many, process_transaction, parse_and_sign from neo.Prompt.Commands.Tokens import token_approve_allowance, token_get_allowance, token_send, token_send_from, \ token_mint, token_crowdsale_register, token_history @@ -133,7 +133,7 @@ class PromptInterface: # 'import token {token_contract_hash}', # 'export wif {address}', # 'export nep2 {address}', - # 'open wallet {path}', + # 'open wallet {path}', #DONE # 'create wallet {path}', #DONE # 'wallet (verbose)', #DONE # 'wallet claim (max_coins_to_claim)', @@ -152,10 +152,10 @@ class PromptInterface: # 'wallet tkn_history {token symbol}', # 'wallet unspent (neo/gas)', # 'wallet split {addr} {asset} {unspent index} {divide into number of vins}', - # 'wallet close', - # 'send {assetId or name} {address} {amount} (--from-addr={addr}) (--fee={priority_fee}) (--owners=[{addr}, ...]) (--tx-attr=[{"usage": ,"data":""}, ...])', - # 'sendmany {number of outgoing tx} (--change-addr={addr}) (--from-addr={addr}) (--fee={priority_fee}) (--owners=[{addr}, ...]) (--tx-attr=[{"usage": ,"data":""}, ...])', - # 'sign {transaction in JSON format}', + # 'wallet close', #DONE + # 'send {assetId or name} {address} {amount} (--from-addr={addr}) (--fee={priority_fee}) (--owners=[{addr}, ...]) (--tx-attr=[{"usage": ,"data":""}, ...])', #DONE + # 'sendmany {number of outgoing tx} (--change-addr={addr}) (--from-addr={addr}) (--fee={priority_fee}) (--owners=[{addr}, ...]) (--tx-attr=[{"usage": ,"data":""}, ...])', #DONE + # 'sign {transaction in JSON format}', #DONE # 'testinvoke {contract hash} [{params} or --i] (--attach-neo={amount}, --attach-gas={amount}) (--from-addr={addr}) --no-parse-addr (parse address strings to script hash bytearray)', # 'debugstorage {on/off/reset}' # ] @@ -206,14 +206,14 @@ def get_completer(self): # 'withdraw_reqest', 'completed', 'cancel', 'cleanup', # 'all', 'debugstorage', 'compiler-nep8', ] - if self.Wallet: - for addr in self.Wallet.Addresses: + if PromptData.Wallet: + for addr in PromptData.Wallet.Addresses: if addr not in self._known_things: self._known_things.append(addr) - for alias in self.Wallet.NamedAddr: + for alias in PromptData.Wallet.NamedAddr: if alias.Title not in self._known_things: self._known_things.append(alias.Title) - for tkn in self.Wallet.GetTokens().values(): + for tkn in PromptData.Wallet.GetTokens().values(): if tkn.symbol not in self._known_things: self._known_things.append(tkn.symbol) @@ -226,7 +226,7 @@ def get_completer(self): def quit(self): print('Shutting down. This may take a bit...') self.go_on = False - self.do_close_wallet() + PromptData.close_wallet() reactor.stop() def help(self): @@ -239,37 +239,37 @@ def help(self): tokens.append(("class:command", f"\nRun 'COMMAND help' for more information on a command.")) print_formatted_text(FormattedText(tokens), style=self.token_style) - def do_open(self, arguments): - if self.Wallet: - self.do_close_wallet() + # def do_open(self, arguments): + # if self.Wallet: + # self.do_close_wallet() - item = get_arg(arguments) + # item = get_arg(arguments) - if item and item == 'wallet': + # if item and item == 'wallet': - path = get_arg(arguments, 1) + # path = get_arg(arguments, 1) - if path: + # if path: - if not os.path.exists(path): - print("Wallet file not found") - return + # if not os.path.exists(path): + # print("Wallet file not found") + # return - passwd = prompt("[password]> ", is_password=True) - password_key = to_aes_key(passwd) + # passwd = prompt("[password]> ", is_password=True) + # password_key = to_aes_key(passwd) - try: - self.Wallet = UserWallet.Open(path, password_key) + # try: + # self.Wallet = UserWallet.Open(path, password_key) - self.start_wallet_loop() - print("Opened wallet at %s" % path) - except Exception as e: - print("Could not open wallet: %s" % e) + # self.start_wallet_loop() + # print("Opened wallet at %s" % path) + # except Exception as e: + # print("Could not open wallet: %s" % e) - else: - print("Please specify a path") - else: - print("Please specify something to open") + # else: + # print("Please specify a path") + # else: + # print("Please specify something to open") # def do_create(self, arguments): # item = get_arg(arguments) @@ -319,7 +319,7 @@ def do_open(self, arguments): def start_wallet_loop(self): if self.wallet_loop_deferred: self.stop_wallet_loop() - self.walletdb_loop = task.LoopingCall(self.Wallet.ProcessBlocks) + self.walletdb_loop = task.LoopingCall(PromptData.Wallet.ProcessBlocks) self.wallet_loop_deferred = self.walletdb_loop.start(1) self.wallet_loop_deferred.addErrback(self.on_looperror) @@ -329,13 +329,13 @@ def stop_wallet_loop(self): if self.walletdb_loop and self.walletdb_loop.running: self.walletdb_loop.stop() - def do_close_wallet(self): - if self.Wallet: - path = self.Wallet._path - self.stop_wallet_loop() - self.Wallet.Close() - self.Wallet = None - print("Closed wallet %s" % path) + # def do_close_wallet(self): + # if self.Wallet: + # path = self.Wallet._path + # self.stop_wallet_loop() + # self.Wallet.Close() + # self.Wallet = None + # print("Closed wallet %s" % path) # def do_import(self, arguments): # item = get_arg(arguments)