Browse Source

test suite: `ThornodeServer` -> `ThornodeSwapServer`

The MMGen Project 7 months ago
parent
commit
800b3cef36

+ 3 - 3
test/cmdtest_d/ethbump.py

@@ -22,14 +22,14 @@ from ..include.common import imsg, omsg_r
 
 
 from .include.common import cleanup_env, dfl_words_file, dfl_sid
 from .include.common import cleanup_env, dfl_words_file, dfl_sid
 from .include.runner import CmdTestRunner
 from .include.runner import CmdTestRunner
-from .httpd.thornode import ThornodeServer
+from .httpd.thornode_swap import ThornodeSwapServer
 
 
 from .ethdev import CmdTestEthdev, CmdTestEthdevMethods
 from .ethdev import CmdTestEthdev, CmdTestEthdevMethods
 from .regtest import CmdTestRegtest
 from .regtest import CmdTestRegtest
 from .swap import CmdTestSwapMethods
 from .swap import CmdTestSwapMethods
 from .ethswap import CmdTestEthSwapMethods
 from .ethswap import CmdTestEthSwapMethods
 
 
-thornode_server = ThornodeServer()
+swap_server = ThornodeSwapServer()
 burn_addr = 'beefcafe22' * 4
 burn_addr = 'beefcafe22' * 4
 method_template = """
 method_template = """
 def {name}(self):
 def {name}(self):
@@ -292,7 +292,7 @@ class CmdTestEthBump(CmdTestEthBumpMethods, CmdTestEthSwapMethods, CmdTestSwapMe
 		ethbump_ltc = CmdTestRunner(cfg, t.repo_root, t.data_dir, t.trash_dir, t.trash_dir2)
 		ethbump_ltc = CmdTestRunner(cfg, t.repo_root, t.data_dir, t.trash_dir, t.trash_dir2)
 		ethbump_ltc.init_group('ethbump_ltc')
 		ethbump_ltc.init_group('ethbump_ltc')
 
 
-		thornode_server.start()
+		swap_server.start()
 
 
 	def txcreate1(self):
 	def txcreate1(self):
 		return self._txcreate(args=[f'{burn_addr},987'], acct='1')
 		return self._txcreate(args=[f'{burn_addr},987'], acct='1')

+ 6 - 6
test/cmdtest_d/ethswap.py

@@ -23,13 +23,13 @@ from ..include.common import imsg, chk_equal
 
 
 from .include.runner import CmdTestRunner
 from .include.runner import CmdTestRunner
 from .include.common import dfl_sid, eth_inbound_addr, thorchain_router_addr_file
 from .include.common import dfl_sid, eth_inbound_addr, thorchain_router_addr_file
-from .httpd.thornode import ThornodeServer
+from .httpd.thornode_swap import ThornodeSwapServer
 
 
 from .regtest import CmdTestRegtest
 from .regtest import CmdTestRegtest
 from .swap import CmdTestSwapMethods
 from .swap import CmdTestSwapMethods
 from .ethdev import CmdTestEthdev
 from .ethdev import CmdTestEthdev
 
 
-thornode_server = ThornodeServer()
+swap_server = ThornodeSwapServer()
 
 
 method_template = """
 method_template = """
 def {name}(self):
 def {name}(self):
@@ -150,7 +150,7 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
 		('subgroup.eth_token_swap', ['fund', 'token_init']),
 		('subgroup.eth_token_swap', ['fund', 'token_init']),
 		('stop',                    'stopping regtest daemon'),
 		('stop',                    'stopping regtest daemon'),
 		('eth_stop',                'stopping Ethereum daemon'),
 		('eth_stop',                'stopping Ethereum daemon'),
-		('thornode_server_stop',    'stopping the Thornode server'),
+		('swap_server_stop',        'stopping the Thornode server'),
 	)
 	)
 	cmd_subgroups = {
 	cmd_subgroups = {
 	'init': (
 	'init': (
@@ -281,7 +281,7 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
 		ethswap_eth = CmdTestRunner(cfg, t.repo_root, t.data_dir, t.trash_dir, t.trash_dir2)
 		ethswap_eth = CmdTestRunner(cfg, t.repo_root, t.data_dir, t.trash_dir, t.trash_dir2)
 		ethswap_eth.init_group(self.eth_group)
 		ethswap_eth.init_group(self.eth_group)
 
 
-		thornode_server.start()
+		swap_server.start()
 
 
 	def swaptxcreate1(self):
 	def swaptxcreate1(self):
 		t = self._swaptxcreate(['BTC', '8.765', 'ETH'])
 		t = self._swaptxcreate(['BTC', '8.765', 'ETH'])
@@ -326,13 +326,13 @@ class CmdTestEthSwap(CmdTestSwapMethods, CmdTestRegtest):
 		t.expect('OK? (Y/n): ', 'y')
 		t.expect('OK? (Y/n): ', 'y')
 		return self._swaptxcreate_ui_common(t)
 		return self._swaptxcreate_ui_common(t)
 
 
-	def thornode_server_stop(self):
+	def swap_server_stop(self):
 		self.spawn(msg_only=True)
 		self.spawn(msg_only=True)
 		if self.cfg.no_daemon_stop:
 		if self.cfg.no_daemon_stop:
 			msg_r('(leaving thornode server running by user request)')
 			msg_r('(leaving thornode server running by user request)')
 			imsg('')
 			imsg('')
 		else:
 		else:
-			thornode_server.stop()
+			swap_server.stop()
 		return 'ok'
 		return 'ok'
 
 
 class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev):
 class CmdTestEthSwapEth(CmdTestEthSwapMethods, CmdTestSwapMethods, CmdTestEthdev):

+ 0 - 153
test/cmdtest_d/httpd/thornode.py

@@ -12,162 +12,9 @@
 test.cmdtest_d.httpd.thornode: Thornode WSGI http server
 test.cmdtest_d.httpd.thornode: Thornode WSGI http server
 """
 """
 
 
-import time, re, json
-
-from mmgen.cfg import Config
-from mmgen.amt import UniAmt
-from mmgen.protocol import init_proto
-
-from ..include.common import eth_inbound_addr, thorchain_router_addr_file
-
 from . import HTTPD
 from . import HTTPD
 
 
-cfg = Config()
-
-# https://thornode.ninerealms.com/thorchain/quote/swap?from_asset=BCH.BCH&to_asset=LTC.LTC&amount=1000000
-sample_request = 'GET /thorchain/quote/swap?from_asset=BCH.BCH&to_asset=LTC.LTC&amount=1000000000'
-request_pat = r'/thorchain/quote/swap\?from_asset=(\S+)\.(\S+)&to_asset=(\S+)\.(\S+)&amount=(\d+)'
-prices = {'BTC': 97000, 'LTC': 115, 'BCH': 330, 'ETH': 2304, 'MM1': 0.998, 'RUNE': 1.4}
-gas_rate_units = {'ETH': 'gwei', 'BTC': 'satsperbyte'}
-recommended_gas_rate = {'ETH': '1', 'BTC': '6'}
-
-data_template_from_rune = {
-	'outbound_delay_blocks': 0,
-	'outbound_delay_seconds': 0,
-	'fees': {
-		'asset': 'BTC.BTC',
-		'affiliate': '0',
-		'outbound': '1182',
-		'liquidity': '110',
-		'total': '1292',
-		'slippage_bps': 7,
-		'total_bps': 92
-	},
-	'warning': 'Do not cache this response. Do not send funds after the expiry.',
-	'notes': 'Broadcast a MsgDeposit to the THORChain network with the appropriate memo. Do not use multi-in, multi-out transactions.',
-	'max_streaming_quantity': 0,
-	'streaming_swap_blocks': 0
-}
-
-data_template_to_rune = {
-	'inbound_confirmation_blocks': 2,
-	'inbound_confirmation_seconds': 24,
-	'outbound_delay_blocks': 0,
-	'outbound_delay_seconds': 0,
-	'fees': {
-		'asset': 'THOR.RUNE',
-		'affiliate': '0',
-		'outbound': '2000000',
-		'liquidity': '684966',
-		'total': '2684966',
-		'slippage_bps': 8,
-		'total_bps': 31
-	},
-	'router': '0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146',
-	'warning': 'Do not cache this response. Do not send funds after the expiry.',
-	'notes': 'Base Asset: Send the inbound_address the asset with the memo encoded in hex in the data field. Tokens: First approve router to spend tokens from user: asset.approve(router, amount). Then call router.depositWithExpiry(inbound_address, asset, amount, memo, expiry). Asset is the token contract address. Amount should be in native asset decimals (eg 1e18 for most tokens). Do not swap to smart contract addresses.',
-	'dust_threshold': '1',
-	'recommended_gas_rate': '1',
-	'max_streaming_quantity': 0,
-	'streaming_swap_blocks': 0,
-	'total_swap_seconds': 24
-}
-
-data_template_btc = {
-	'inbound_confirmation_blocks': 4,
-	'inbound_confirmation_seconds': 2400,
-	'outbound_delay_blocks': 5,
-	'outbound_delay_seconds': 30,
-	'fees': {
-		'asset': 'LTC.LTC',
-		'affiliate': '0',
-		'outbound': '878656',
-		'liquidity': '8945012',
-		'total': '9823668',
-		'slippage_bps': 31,
-		'total_bps': 34
-	},
-	'warning': 'Do not cache this response. Do not send funds after the expiry.',
-	'notes': 'First output should be to inbound_address, second output should be change back to self, third output should be OP_RETURN, limited to 80 bytes. Do not send below the dust threshold. Do not use exotic spend scripts, locks or address formats.',
-	'dust_threshold': '10000',
-	'max_streaming_quantity': 0,
-	'streaming_swap_blocks': 0,
-	'total_swap_seconds': 2430
-}
-
-data_template_eth = {
-	'inbound_confirmation_blocks': 2,
-	'inbound_confirmation_seconds': 24,
-	'outbound_delay_blocks': 0,
-	'outbound_delay_seconds': 0,
-	'fees': {
-		'asset': 'BTC.BTC',
-		'affiliate': '0',
-		'outbound': '1097',
-		'liquidity': '77',
-		'total': '1174',
-		'slippage_bps': 15,
-		'total_bps': 237
-	},
-	'router': '0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146',
-	'warning': 'Do not cache this response. Do not send funds after the expiry.',
-	'notes': 'Base Asset: Send the inbound_address the asset with the memo encoded in hex in the data field. Tokens: First approve router to spend tokens from user: asset.approve(router, amount). Then call router.depositWithExpiry(inbound_address, asset, amount, memo, expiry). Asset is the token contract address. Amount should be in native asset decimals (eg 1e18 for most tokens). Do not swap to smart contract addresses.',
-	'recommended_gas_rate': '1',
-	'max_streaming_quantity': 0,
-	'streaming_swap_blocks': 0,
-	'total_swap_seconds': 24
-}
-
-def make_inbound_addr(proto, mmtype):
-	if proto.is_evm:
-		return '0x' + eth_inbound_addr # non-checksummed as per ninerealms thornode
-	else:
-		from mmgen.tool.coin import tool_cmd
-		n = int(time.time()) // (60 * 60 * 24) # increments once every 24 hrs
-		return tool_cmd(
-			cfg     = cfg,
-			cmdname = 'pubhash2addr',
-			proto   = proto,
-			mmtype  = mmtype).pubhash2addr(f'{n:040x}')
-
 class ThornodeServer(HTTPD):
 class ThornodeServer(HTTPD):
 	name = 'thornode server'
 	name = 'thornode server'
 	port = 18800
 	port = 18800
 	content_type = 'application/json'
 	content_type = 'application/json'
-
-	def make_response_body(self, method, environ):
-		from wsgiref.util import request_uri
-
-		m = re.search(request_pat, request_uri(environ))
-		send_chain, send_asset, recv_chain, recv_asset, amt_atomic = m.groups()
-
-		in_amt = UniAmt(int(amt_atomic), from_unit='satoshi')
-		out_amt = in_amt * (prices[send_asset] / prices[recv_asset])
-
-		data_template = (
-			data_template_from_rune if send_asset == 'RUNE' else
-			data_template_to_rune if recv_asset == 'RUNE' else
-			data_template_eth if send_asset == 'ETH' else
-			data_template_btc)
-
-		data = data_template | {
-			'recommended_min_amount_in': str(int(70 * 10**8 / prices[send_asset])), # $70
-			'expected_amount_out': str(out_amt.to_unit('satoshi')),
-			'expiry': int(time.time()) + (10 * 60),
-		}
-
-		if send_asset != 'RUNE':
-			send_proto = init_proto(cfg, send_chain, network='regtest', need_amt=True)
-			data.update({
-				'inbound_address': make_inbound_addr(send_proto, send_proto.preferred_mmtypes[0]),
-				'gas_rate_units': gas_rate_units[send_proto.base_proto_coin],
-				'recommended_gas_rate': recommended_gas_rate[send_proto.base_proto_coin]
-			})
-
-		if send_asset == 'MM1':
-			eth_proto = init_proto(cfg, 'eth', network='regtest')
-			with open(thorchain_router_addr_file) as fh:
-				raw_addr = fh.read().strip()
-			data['router'] = '0x' + eth_proto.checksummed_addr(raw_addr)
-
-		return json.dumps(data).encode()

+ 171 - 0
test/cmdtest_d/httpd/thornode_swap.py

@@ -0,0 +1,171 @@
+#!/usr/bin/env python3
+#
+# MMGen Wallet, a terminal-based cryptocurrency wallet
+# Copyright (C)2013-2025 The MMGen Project <mmgen@tuta.io>
+# Licensed under the GNU General Public License, Version 3:
+#   https://www.gnu.org/licenses
+# Public project repositories:
+#   https://github.com/mmgen/mmgen-wallet
+#   https://gitlab.com/mmgen/mmgen-wallet
+
+"""
+test.cmdtest_d.httpd.thornode_swap: Thornode swap WSGI http server
+"""
+
+import time, re, json
+from wsgiref.util import request_uri
+
+from mmgen.cfg import Config
+from mmgen.amt import UniAmt
+from mmgen.protocol import init_proto
+
+from ..include.common import eth_inbound_addr, thorchain_router_addr_file
+
+from . import HTTPD
+from .thornode import ThornodeServer
+
+cfg = Config()
+
+# https://thornode.ninerealms.com/thorchain/quote/swap?from_asset=BCH.BCH&to_asset=LTC.LTC&amount=1000000
+prices = {'BTC': 97000, 'LTC': 115, 'BCH': 330, 'ETH': 2304, 'MM1': 0.998, 'RUNE': 1.4}
+gas_rate_units = {'ETH': 'gwei', 'BTC': 'satsperbyte'}
+recommended_gas_rate = {'ETH': '1', 'BTC': '6'}
+
+data_template_from_rune = {
+	'outbound_delay_blocks': 0,
+	'outbound_delay_seconds': 0,
+	'fees': {
+		'asset': 'BTC.BTC',
+		'affiliate': '0',
+		'outbound': '1182',
+		'liquidity': '110',
+		'total': '1292',
+		'slippage_bps': 7,
+		'total_bps': 92
+	},
+	'warning': 'Do not cache this response. Do not send funds after the expiry.',
+	'notes': 'Broadcast a MsgDeposit to the THORChain network with the appropriate memo. Do not use multi-in, multi-out transactions.',
+	'max_streaming_quantity': 0,
+	'streaming_swap_blocks': 0
+}
+
+data_template_to_rune = {
+	'inbound_confirmation_blocks': 2,
+	'inbound_confirmation_seconds': 24,
+	'outbound_delay_blocks': 0,
+	'outbound_delay_seconds': 0,
+	'fees': {
+		'asset': 'THOR.RUNE',
+		'affiliate': '0',
+		'outbound': '2000000',
+		'liquidity': '684966',
+		'total': '2684966',
+		'slippage_bps': 8,
+		'total_bps': 31
+	},
+	'router': '0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146',
+	'warning': 'Do not cache this response. Do not send funds after the expiry.',
+	'notes': 'Base Asset: Send the inbound_address the asset with the memo encoded in hex in the data field. Tokens: First approve router to spend tokens from user: asset.approve(router, amount). Then call router.depositWithExpiry(inbound_address, asset, amount, memo, expiry). Asset is the token contract address. Amount should be in native asset decimals (eg 1e18 for most tokens). Do not swap to smart contract addresses.',
+	'dust_threshold': '1',
+	'recommended_gas_rate': '1',
+	'max_streaming_quantity': 0,
+	'streaming_swap_blocks': 0,
+	'total_swap_seconds': 24
+}
+
+data_template_btc = {
+	'inbound_confirmation_blocks': 4,
+	'inbound_confirmation_seconds': 2400,
+	'outbound_delay_blocks': 5,
+	'outbound_delay_seconds': 30,
+	'fees': {
+		'asset': 'LTC.LTC',
+		'affiliate': '0',
+		'outbound': '878656',
+		'liquidity': '8945012',
+		'total': '9823668',
+		'slippage_bps': 31,
+		'total_bps': 34
+	},
+	'warning': 'Do not cache this response. Do not send funds after the expiry.',
+	'notes': 'First output should be to inbound_address, second output should be change back to self, third output should be OP_RETURN, limited to 80 bytes. Do not send below the dust threshold. Do not use exotic spend scripts, locks or address formats.',
+	'dust_threshold': '10000',
+	'max_streaming_quantity': 0,
+	'streaming_swap_blocks': 0,
+	'total_swap_seconds': 2430
+}
+
+data_template_eth = {
+	'inbound_confirmation_blocks': 2,
+	'inbound_confirmation_seconds': 24,
+	'outbound_delay_blocks': 0,
+	'outbound_delay_seconds': 0,
+	'fees': {
+		'asset': 'BTC.BTC',
+		'affiliate': '0',
+		'outbound': '1097',
+		'liquidity': '77',
+		'total': '1174',
+		'slippage_bps': 15,
+		'total_bps': 237
+	},
+	'router': '0xD37BbE5744D730a1d98d8DC97c42F0Ca46aD7146',
+	'warning': 'Do not cache this response. Do not send funds after the expiry.',
+	'notes': 'Base Asset: Send the inbound_address the asset with the memo encoded in hex in the data field. Tokens: First approve router to spend tokens from user: asset.approve(router, amount). Then call router.depositWithExpiry(inbound_address, asset, amount, memo, expiry). Asset is the token contract address. Amount should be in native asset decimals (eg 1e18 for most tokens). Do not swap to smart contract addresses.',
+	'recommended_gas_rate': '1',
+	'max_streaming_quantity': 0,
+	'streaming_swap_blocks': 0,
+	'total_swap_seconds': 24
+}
+
+def make_inbound_addr(proto, mmtype):
+	if proto.is_evm:
+		return '0x' + eth_inbound_addr # non-checksummed as per ninerealms thornode
+	else:
+		from mmgen.tool.coin import tool_cmd
+		n = int(time.time()) // (60 * 60 * 24) # increments once every 24 hrs
+		return tool_cmd(
+			cfg     = cfg,
+			cmdname = 'pubhash2addr',
+			proto   = proto,
+			mmtype  = mmtype).pubhash2addr(f'{n:040x}')
+
+class ThornodeSwapServer(ThornodeServer):
+	name = 'thornode swap server'
+	request_pat = r'/thorchain/quote/swap\?from_asset=(\S+)\.(\S+)&to_asset=(\S+)\.(\S+)&amount=(\d+)'
+
+	def make_response_body(self, method, environ):
+
+		m = re.search(self.request_pat, request_uri(environ))
+		send_chain, send_asset, recv_chain, recv_asset, amt_atomic = m.groups()
+
+		in_amt = UniAmt(int(amt_atomic), from_unit='satoshi')
+		out_amt = in_amt * (prices[send_asset] / prices[recv_asset])
+
+		data_template = (
+			data_template_from_rune if send_asset == 'RUNE' else
+			data_template_to_rune if recv_asset == 'RUNE' else
+			data_template_eth if send_asset == 'ETH' else
+			data_template_btc)
+
+		data = data_template | {
+			'recommended_min_amount_in': str(int(70 * 10**8 / prices[send_asset])), # $70
+			'expected_amount_out': str(out_amt.to_unit('satoshi')),
+			'expiry': int(time.time()) + (10 * 60),
+		}
+
+		if send_asset != 'RUNE':
+			send_proto = init_proto(cfg, send_chain, network='regtest', need_amt=True)
+			data.update({
+				'inbound_address': make_inbound_addr(send_proto, send_proto.preferred_mmtypes[0]),
+				'gas_rate_units': gas_rate_units[send_proto.base_proto_coin],
+				'recommended_gas_rate': recommended_gas_rate[send_proto.base_proto_coin]
+			})
+
+		if send_asset == 'MM1':
+			eth_proto = init_proto(cfg, 'eth', network='regtest')
+			with open(thorchain_router_addr_file) as fh:
+				raw_addr = fh.read().strip()
+			data['router'] = '0x' + eth_proto.checksummed_addr(raw_addr)
+
+		return json.dumps(data).encode()

+ 6 - 6
test/cmdtest_d/swap.py

@@ -19,12 +19,12 @@ from mmgen.wallet.mmgen import wallet as MMGenWallet
 
 
 from ..include.common import make_burn_addr, gr_uc
 from ..include.common import make_burn_addr, gr_uc
 from .include.common import dfl_bip39_file, dfl_words_file
 from .include.common import dfl_bip39_file, dfl_words_file
-from .httpd.thornode import ThornodeServer
+from .httpd.thornode_swap import ThornodeSwapServer
 
 
 from .autosign import CmdTestAutosign, CmdTestAutosignThreaded
 from .autosign import CmdTestAutosign, CmdTestAutosignThreaded
 from .regtest import CmdTestRegtest, rt_data, dfl_wcls, rt_pw, strip_ansi_escapes
 from .regtest import CmdTestRegtest, rt_data, dfl_wcls, rt_pw, strip_ansi_escapes
 
 
-thornode_server = ThornodeServer()
+swap_server = ThornodeSwapServer()
 
 
 sample1 = gr_uc[:24]
 sample1 = gr_uc[:24]
 sample2 = '00010203040506'
 sample2 = '00010203040506'
@@ -280,7 +280,7 @@ class CmdTestSwap(CmdTestSwapMethods, CmdTestRegtest, CmdTestAutosignThreaded):
 		('subgroup.signsend',     ['init_swap']),
 		('subgroup.signsend',     ['init_swap']),
 		('subgroup.signsend_bad', ['init_swap']),
 		('subgroup.signsend_bad', ['init_swap']),
 		('subgroup.autosign',     ['init_data', 'signsend']),
 		('subgroup.autosign',     ['init_data', 'signsend']),
-		('thornode_server_stop',  'stopping the Thornode server'),
+		('swap_server_stop',      'stopping the Thornode server'),
 		('stop',                  'stopping regtest daemons'),
 		('stop',                  'stopping regtest daemons'),
 	)
 	)
 	cmd_subgroups = {
 	cmd_subgroups = {
@@ -408,7 +408,7 @@ class CmdTestSwap(CmdTestSwapMethods, CmdTestRegtest, CmdTestAutosignThreaded):
 
 
 		self.protos = [init_proto(cfg, k, network='regtest', need_amt=True) for k in ('btc', 'ltc', 'bch')]
 		self.protos = [init_proto(cfg, k, network='regtest', need_amt=True) for k in ('btc', 'ltc', 'bch')]
 
 
-		thornode_server.start()
+		swap_server.start()
 
 
 		self.opts.append('--bob')
 		self.opts.append('--bob')
 
 
@@ -776,7 +776,7 @@ class CmdTestSwap(CmdTestSwapMethods, CmdTestRegtest, CmdTestAutosignThreaded):
 	def mempool2(self):
 	def mempool2(self):
 		return self._mempool(2)
 		return self._mempool(2)
 
 
-	def thornode_server_stop(self):
+	def swap_server_stop(self):
 		self.spawn(msg_only=True)
 		self.spawn(msg_only=True)
-		thornode_server.stop()
+		swap_server.stop()
 		return 'ok'
 		return 'ok'