88from neo .Prompt .Commands import Send , Wallet
99from neo .Prompt .PromptData import PromptData
1010import shutil
11- from mock import patch
11+ from mock import patch , MagicMock
1212import json
1313from io import StringIO
1414from neo .Prompt .PromptPrinter import pp
@@ -23,6 +23,14 @@ class UserWalletTestCase(WalletFixtureTestCase):
2323 watch_addr_str = 'AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkEm'
2424 _wallet1 = None
2525
26+ wallet_2_addr = 'AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkEm'
27+ _wallet2 = None
28+
29+ wallet_3_addr = 'AZiE7xfyJALW7KmADWtCJXGGcnduYhGiCX'
30+ _wallet3 = None
31+
32+ wallet_2_and_3_multisig_addr = "Aau2M4UdXxwxLLizDw11eDZRDs5jpXduh8"
33+
2634 @classmethod
2735 def GetWallet1 (cls , recreate = False ):
2836 if cls ._wallet1 is None or recreate :
@@ -31,6 +39,22 @@ def GetWallet1(cls, recreate=False):
3139 to_aes_key (UserWalletTestCase .wallet_1_pass ()))
3240 return cls ._wallet1
3341
42+ @classmethod
43+ def GetWallet2 (cls , recreate = False ):
44+ if cls ._wallet2 is None or recreate :
45+ shutil .copyfile (cls .wallet_2_path (), cls .wallet_2_dest ())
46+ cls ._wallet2 = UserWallet .Open (UserWalletTestCase .wallet_2_dest (),
47+ to_aes_key (UserWalletTestCase .wallet_2_pass ()))
48+ return cls ._wallet2
49+
50+ @classmethod
51+ def GetWallet3 (cls , recreate = False ):
52+ if cls ._wallet3 is None or recreate :
53+ shutil .copyfile (cls .wallet_3_path (), cls .wallet_3_dest ())
54+ cls ._wallet3 = UserWallet .Open (UserWalletTestCase .wallet_3_dest (),
55+ to_aes_key (UserWalletTestCase .wallet_3_pass ()))
56+ return cls ._wallet3
57+
3458 @classmethod
3559 def tearDown (cls ):
3660 PromptData .Wallet = None
@@ -39,7 +63,7 @@ def test_send_neo(self):
3963 with patch ('sys.stdout' , new = StringIO ()) as mock_print :
4064 with patch ('neo.Prompt.Commands.Send.prompt' , side_effect = [UserWalletTestCase .wallet_1_pass ()]):
4165 PromptData .Wallet = self .GetWallet1 (recreate = True )
42- args = ['send' , 'neo' , self .watch_addr_str , '50 ' ]
66+ args = ['send' , 'neo' , self .watch_addr_str , '1 ' ]
4367
4468 res = Wallet .CommandWallet ().execute (args )
4569
@@ -50,7 +74,7 @@ def test_send_gas(self):
5074 with patch ('sys.stdout' , new = StringIO ()) as mock_print :
5175 with patch ('neo.Prompt.Commands.Send.prompt' , side_effect = [UserWalletTestCase .wallet_1_pass ()]):
5276 PromptData .Wallet = self .GetWallet1 (recreate = True )
53- args = ['send' , 'gas' , self .watch_addr_str , '5 ' ]
77+ args = ['send' , 'gas' , self .watch_addr_str , '1 ' ]
5478
5579 res = Wallet .CommandWallet ().execute (args )
5680
@@ -546,3 +570,112 @@ def test_sendmany_keyboard_interrupt(self):
546570
547571 self .assertFalse (res )
548572 self .assertIn ("Transaction cancelled" , mock_print .getvalue ())
573+
574+ def test_parse_and_sign_good (self ):
575+ with patch ('neo.Prompt.Commands.Send.prompt' , side_effect = [UserWalletTestCase .wallet_2_pass ()]):
576+ # start the tx from wallet2
577+ PromptData .Wallet = self .GetWallet2 (recreate = True )
578+ args = ['send' , 'neo' , self .wallet_1_addr , '1' , '--from-addr=' + self .wallet_2_and_3_multisig_addr ]
579+
580+ Wallet .CommandWallet ().execute (args )
581+
582+ # now sign the tx with wallet3
583+ PromptData .Wallet = self .GetWallet3 (recreate = True )
584+ jsn = '{"type":"Neo.Core.ContractTransaction","hex":"800000014405fd5ae29ceeb20912776048c544109c8c67c4128c019863eca58cf677ad360000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500e1f505000000001cc9c05cefffe6cdd7b182816a9152ec218d2ec09b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50084d71700000000d1c4904014bfe7d34e9e97370f2cd3a633377cd6","items":{"0xd67c3733a6d32c0f37979e4ed3e7bf144090c4d1":{"script":"522103989f7417da540a8ce00195738249291cba058102a12d2df1b00e2a826d8bd0612103c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e9603452ae","parameters":[{"type":"Signature"},{"type":"Signature"}],"signatures":{"03c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e96034":"b5b32d6b56f3729747380072c722c50b0ee91e930f58a58d49c98c5543e335b70f6a400c8e1f9fa9653f7605ad229974cacfac3143cd355ca900c328b3db6018"}}}}'
585+ args = ['sign' , jsn ]
586+
587+ res = Wallet .CommandWallet ().execute (args )
588+
589+ res = res .ToJson ()
590+ self .assertTrue (res )
591+ self .assertEqual (res ['vout' ][0 ]['value' ], "1" ) # verify the amount
592+ self .assertEqual (res ['vout' ][0 ]['address' ], self .wallet_1_addr ) # verify to_address
593+ self .assertEqual (res ['vout' ][1 ]['address' ], self .wallet_2_and_3_multisig_addr ) # verify from_address
594+
595+ def test_parse_and_sign_bad_jsn (self ):
596+ with patch ('sys.stdout' , new = StringIO ()) as mock_print :
597+ with patch ('neo.Prompt.Commands.Send.prompt' , side_effect = [UserWalletTestCase .wallet_2_pass ()]):
598+ # start the tx from wallet2
599+ PromptData .Wallet = self .GetWallet2 (recreate = True )
600+ args = ['send' , 'neo' , self .wallet_1_addr , '1' , '--from-addr=' + self .wallet_2_and_3_multisig_addr ]
601+
602+ Wallet .CommandWallet ().execute (args )
603+
604+ # now sign the tx with wallet3
605+ PromptData .Wallet = self .GetWallet3 (recreate = True )
606+ jsn = 'blah'
607+ args = ['sign' , jsn ]
608+
609+ res = Wallet .CommandWallet ().execute (args )
610+
611+ self .assertFalse (res )
612+ self .assertIn ("Failed to parse JSON" , mock_print .getvalue ())
613+
614+ def test_parse_and_sign_fails_to_relay (self ):
615+ with patch ('sys.stdout' , new = StringIO ()) as mock_print :
616+ with patch ('neo.Prompt.Commands.Send.prompt' , side_effect = [UserWalletTestCase .wallet_2_pass ()]):
617+ with patch ('neo.Prompt.Commands.Send.NodeLeader.Relay' , return_value = False ):
618+ # start the tx from wallet2
619+ PromptData .Wallet = self .GetWallet2 (recreate = True )
620+ args = ['send' , 'neo' , self .wallet_1_addr , '1' , '--from-addr=' + self .wallet_2_and_3_multisig_addr ]
621+
622+ Wallet .CommandWallet ().execute (args )
623+
624+ # now sign the tx with wallet3
625+ PromptData .Wallet = self .GetWallet3 (recreate = True )
626+ jsn = '{"type":"Neo.Core.ContractTransaction","hex":"800000014405fd5ae29ceeb20912776048c544109c8c67c4128c019863eca58cf677ad360000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500e1f505000000001cc9c05cefffe6cdd7b182816a9152ec218d2ec09b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50084d71700000000d1c4904014bfe7d34e9e97370f2cd3a633377cd6","items":{"0xd67c3733a6d32c0f37979e4ed3e7bf144090c4d1":{"script":"522103989f7417da540a8ce00195738249291cba058102a12d2df1b00e2a826d8bd0612103c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e9603452ae","parameters":[{"type":"Signature"},{"type":"Signature"}],"signatures":{"03c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e96034":"b5b32d6b56f3729747380072c722c50b0ee91e930f58a58d49c98c5543e335b70f6a400c8e1f9fa9653f7605ad229974cacfac3143cd355ca900c328b3db6018"}}}}'
627+ args = ['sign' , jsn ]
628+
629+ res = Wallet .CommandWallet ().execute (args )
630+
631+ self .assertFalse (res )
632+ self .assertIn ("Could not relay tx" , mock_print .getvalue ())
633+
634+ def test_parse_and_sign_twice (self ): # this test implies there are more signatures needed
635+ with patch ('sys.stdout' , new = StringIO ()) as mock_print :
636+ with patch ('neo.Prompt.Commands.Send.prompt' , side_effect = [UserWalletTestCase .wallet_2_pass ()]):
637+ # start the tx from wallet2
638+ PromptData .Wallet = self .GetWallet2 (recreate = True )
639+ args = ['send' , 'neo' , self .wallet_1_addr , '1' , '--from-addr=' + self .wallet_2_and_3_multisig_addr ]
640+
641+ Wallet .CommandWallet ().execute (args )
642+
643+ # now sign the tx with wallet2 again
644+ jsn = '{"type":"Neo.Core.ContractTransaction","hex":"800000014405fd5ae29ceeb20912776048c544109c8c67c4128c019863eca58cf677ad360000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500e1f505000000001cc9c05cefffe6cdd7b182816a9152ec218d2ec09b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50084d71700000000d1c4904014bfe7d34e9e97370f2cd3a633377cd6","items":{"0xd67c3733a6d32c0f37979e4ed3e7bf144090c4d1":{"script":"522103989f7417da540a8ce00195738249291cba058102a12d2df1b00e2a826d8bd0612103c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e9603452ae","parameters":[{"type":"Signature"},{"type":"Signature"}],"signatures":{"03c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e96034":"b5b32d6b56f3729747380072c722c50b0ee91e930f58a58d49c98c5543e335b70f6a400c8e1f9fa9653f7605ad229974cacfac3143cd355ca900c328b3db6018"}}}}'
645+ args = ['sign' , jsn ]
646+
647+ res = Wallet .CommandWallet ().execute (args )
648+
649+ self .assertFalse (res )
650+ self .assertIn ("Transaction initiated, but the signature is incomplete" , mock_print .getvalue ())
651+
652+ def test_parse_and_sign_exception (self ):
653+ with patch ('sys.stdout' , new = StringIO ()) as mock_print :
654+ with patch ('neo.Prompt.Commands.Send.prompt' , side_effect = [UserWalletTestCase .wallet_2_pass ()]):
655+ with patch ('neo.Prompt.Commands.Send.traceback' ): # mocking traceback module to avoid stacktrace printing during test run
656+ # start the tx from wallet2
657+ PromptData .Wallet = self .GetWallet2 (recreate = True )
658+ args = ['send' , 'neo' , self .wallet_1_addr , '1' , '--from-addr=' + self .wallet_2_and_3_multisig_addr ]
659+
660+ Wallet .CommandWallet ().execute (args )
661+
662+ # mocking wallet to trigger the exception
663+ PromptData .Wallet = MagicMock ()
664+ PromptData .Wallet .Sign .side_effect = Exception
665+ jsn = '{"type":"Neo.Core.ContractTransaction","hex":"800000014405fd5ae29ceeb20912776048c544109c8c67c4128c019863eca58cf677ad360000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500e1f505000000001cc9c05cefffe6cdd7b182816a9152ec218d2ec09b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50084d71700000000d1c4904014bfe7d34e9e97370f2cd3a633377cd6","items":{"0xd67c3733a6d32c0f37979e4ed3e7bf144090c4d1":{"script":"522103989f7417da540a8ce00195738249291cba058102a12d2df1b00e2a826d8bd0612103c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e9603452ae","parameters":[{"type":"Signature"},{"type":"Signature"}],"signatures":{"03c46aec8d1ac8cb58fe74764de223d15e7045de67a51d1a4bcecd396918e96034":"b5b32d6b56f3729747380072c722c50b0ee91e930f58a58d49c98c5543e335b70f6a400c8e1f9fa9653f7605ad229974cacfac3143cd355ca900c328b3db6018"}}}}'
666+ args = ['sign' , jsn ]
667+
668+ res = Wallet .CommandWallet ().execute (args )
669+
670+ self .assertFalse (res )
671+ self .assertIn ("Could not send:" , mock_print .getvalue ())
672+
673+ def test_parse_and_sign_no_args (self ):
674+ with patch ('sys.stdout' , new = StringIO ()) as mock_print :
675+ PromptData .Wallet = self .GetWallet2 (recreate = True )
676+ args = ['sign' ]
677+
678+ res = Wallet .CommandWallet ().execute (args )
679+
680+ self .assertFalse (res )
681+ self .assertIn ("Please specify the required parameter" , mock_print .getvalue ())
0 commit comments