ethswap.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #!/usr/bin/env python3
  2. #
  3. # MMGen Wallet, a terminal-based cryptocurrency wallet
  4. # Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
  5. # Licensed under the GNU General Public License, Version 3:
  6. # https://www.gnu.org/licenses
  7. # Public project repositories:
  8. # https://github.com/mmgen/mmgen-wallet
  9. # https://gitlab.com/mmgen/mmgen-wallet
  10. """
  11. test.cmdtest_d.ethswap: Ethereum swap tests for the cmdtest.py test suite
  12. """
  13. from mmgen.wallet.mmgen import wallet as MMGenWallet
  14. from mmgen.cfg import Config
  15. from mmgen.protocol import init_proto
  16. from .include.runner import CmdTestRunner
  17. from .include.common import dfl_words_file, dfl_seed_id, rt_pw
  18. from .httpd.thornode import ThornodeServer
  19. from .regtest import CmdTestRegtest
  20. from .swap import CmdTestSwapMethods
  21. from .ethdev import CmdTestEthdev
  22. thornode_server = ThornodeServer()
  23. method_template = """
  24. def {name}(self):
  25. self.spawn(log_only=True)
  26. return ethswap_eth.run_test("{eth_name}", sub=True)
  27. """
  28. class CmdTestEthSwap(CmdTestRegtest, CmdTestSwapMethods):
  29. 'Ethereum swap operations'
  30. bdb_wallet = True
  31. tmpdir_nums = [47]
  32. networks = ('btc',)
  33. passthru_opts = ('coin', 'rpc_backend', 'eth_daemon_id')
  34. cmd_group_in = (
  35. ('setup', 'regtest (Bob and Alice) mode setup'),
  36. ('eth_setup', 'Ethereum devnet setup'),
  37. ('subgroup.init', []),
  38. ('subgroup.fund', ['init']),
  39. ('subgroup.eth_init', []),
  40. ('subgroup.eth_fund', ['eth_init']),
  41. ('subgroup.swap', ['fund', 'eth_fund']),
  42. ('subgroup.eth_swap', ['fund', 'eth_fund']),
  43. ('stop', 'stopping regtest daemon'),
  44. ('eth_stop', 'stopping Ethereum daemon'),
  45. ('thornode_server_stop', 'stopping the Thornode server'),
  46. )
  47. cmd_subgroups = {
  48. 'init': (
  49. 'creating Bob’s MMGen wallet and tracking wallet',
  50. ('walletconv_bob', 'wallet creation (Bob)'),
  51. ('addrgen_bob', 'address generation (Bob)'),
  52. ('addrimport_bob', 'importing Bob’s addresses'),
  53. ),
  54. 'fund': (
  55. 'funding Bob’s wallet',
  56. ('bob_import_miner_addr', 'importing miner’s coinbase addr into Bob’s wallet'),
  57. ('fund_bob', 'funding Bob’s wallet'),
  58. ('generate', 'mining a block'),
  59. ('bob_bal1', 'Bob’s balance'),
  60. ),
  61. 'eth_init': (
  62. 'initializing the ETH tracking wallet',
  63. ('eth_addrgen', ''),
  64. ('eth_addrimport', ''),
  65. ('eth_addrimport_dev_addr', ''),
  66. ('eth_fund_dev_address', ''),
  67. ),
  68. 'eth_fund': (
  69. 'funding the ETH tracking wallet',
  70. ('eth_txcreate1', ''),
  71. ('eth_txsign1', ''),
  72. ('eth_txsend1', ''),
  73. ('eth_bal1', ''),
  74. ),
  75. 'swap': (
  76. 'swap operations (BTC -> ETH)',
  77. ('swaptxcreate1', 'creating a BTC->ETH swap transaction'),
  78. ('swaptxcreate2', 'creating a BTC->ETH swap transaction (used account)'),
  79. ('swaptxsign1', 'signing the swap transaction'),
  80. ('swaptxsend1', 'sending the swap transaction'),
  81. ('generate', 'generating a block'),
  82. ('bob_bal2', 'Bob’s balance'),
  83. ),
  84. 'eth_swap': (
  85. 'swap operations (ETH -> BTC)',
  86. ('eth_swaptxcreate1', ''),
  87. ('eth_swaptxcreate2', ''),
  88. ('eth_swaptxsign1', ''),
  89. ('eth_swaptxsend1', ''),
  90. ('eth_swaptxstatus1', ''),
  91. ('eth_bal2', ''),
  92. ),
  93. }
  94. eth_tests = [c[0] for v in tuple(cmd_subgroups.values()) + (cmd_group_in,)
  95. for c in v if isinstance(c, tuple) and c[0].startswith('eth_')]
  96. exec(''.join(method_template.format(name=k, eth_name=k.removeprefix('eth_')) for k in eth_tests))
  97. def __init__(self, cfg, trunner, cfgs, spawn):
  98. super().__init__(cfg, trunner, cfgs, spawn)
  99. if not trunner:
  100. return
  101. global ethswap_eth
  102. cfg = Config({
  103. '_clone': trunner.cfg,
  104. 'proto': init_proto(cfg, network_id='eth'),
  105. 'resume': None,
  106. 'resume_after': None,
  107. 'exit_after': None,
  108. 'eth_daemon_id': trunner.cfg.eth_daemon_id,
  109. 'log': None,
  110. 'coin': 'eth'})
  111. t = trunner
  112. ethswap_eth = CmdTestRunner(cfg, t.repo_root, t.data_dir, t.trash_dir, t.trash_dir2)
  113. ethswap_eth.init_group('ethswap_eth')
  114. thornode_server.start()
  115. def walletconv_bob(self):
  116. t = self.spawn(
  117. 'mmgen-walletconv',
  118. ['--bob', '--quiet', '-r0', f'-d{self.cfg.data_dir}/regtest/bob', dfl_words_file],
  119. no_passthru_opts = ['coin', 'eth_daemon_id'])
  120. t.hash_preset(MMGenWallet.desc, '1')
  121. t.passphrase_new('new '+MMGenWallet.desc, rt_pw)
  122. t.label()
  123. return t
  124. def swaptxcreate1(self):
  125. self.get_file_with_ext('rawtx', delete_all=True)
  126. t = self._swaptxcreate(['BTC', '8.765', 'ETH'])
  127. t.expect('OK? (Y/n): ', 'y')
  128. t.expect(':E:2')
  129. t.expect('OK? (Y/n): ', 'y')
  130. return self._swaptxcreate_ui_common(t)
  131. def swaptxcreate2(self):
  132. self.get_file_with_ext('rawtx', delete_all=True)
  133. t = self._swaptxcreate(['BTC', '8.765', 'ETH', f'{dfl_seed_id}:E:1'])
  134. t.expect('OK? (Y/n): ', 'y')
  135. return self._swaptxcreate_ui_common(t)
  136. def swaptxsign1(self):
  137. return self._swaptxsign()
  138. def swaptxsend1(self):
  139. return self._swaptxsend()
  140. def bob_bal2(self):
  141. return self._user_bal_cli('bob', chk='491.23498314')
  142. def thornode_server_stop(self):
  143. self.spawn(msg_only=True)
  144. thornode_server.stop()
  145. return 'ok'
  146. class CmdTestEthSwapEth(CmdTestEthdev, CmdTestSwapMethods):
  147. 'Ethereum swap operations - Ethereum wallet'
  148. networks = ('eth',)
  149. tmpdir_nums = [48]
  150. bals = lambda self, k: {
  151. 'swap1': [('98831F3A:E:1', '123.456')],
  152. 'swap2': [('98831F3A:E:1', '114.690978056')],
  153. }[k]
  154. cmd_group_in = CmdTestEthdev.cmd_group_in + (
  155. ('swaptxcreate1', 'creating an ETH->BTC swap transaction'),
  156. ('swaptxcreate2', 'creating an ETH->BTC swap transaction (specific address, trade limit)'),
  157. ('swaptxsign1', 'signing the transaction'),
  158. ('swaptxsend1', 'sending the transaction'),
  159. ('swaptxstatus1', 'getting the transaction status (with --verbose)'),
  160. ('bal1', 'the ETH balance'),
  161. ('bal2', 'the ETH balance'),
  162. )
  163. def swaptxcreate1(self):
  164. self.get_file_with_ext('rawtx', delete_all=True)
  165. t = self._swaptxcreate(['ETH', '8.765', 'BTC'])
  166. t.expect('Continue? (Y/n):', 'y')
  167. t.expect('OK? (Y/n): ', 'y')
  168. return self._swaptxcreate_ui_common(t)
  169. def swaptxcreate2(self):
  170. self.get_file_with_ext('rawtx', delete_all=True)
  171. t = self._swaptxcreate(
  172. ['ETH', '8.765', 'BTC', f'{dfl_seed_id}:B:3'],
  173. add_opts = ['--trade-limit=3%'])
  174. t.expect('Continue? (Y/n):', 'y')
  175. return self._swaptxcreate_ui_common(t, expect=':2019e4/1/0')
  176. def swaptxsign1(self):
  177. return self._swaptxsign()
  178. def swaptxsend1(self):
  179. return self._swaptxsend()
  180. def swaptxstatus1(self):
  181. self.mining_delay()
  182. return self._swaptxsend(add_opts=['--verbose', '--status'], status=True)
  183. def bal1(self):
  184. return self.bal('swap1')
  185. def bal2(self):
  186. return self.bal('swap2')