diff --git a/mmgen/proto/btc/tx/completed.py b/mmgen/proto/btc/tx/completed.py index 16b0baa4..05e42558 100755 --- a/mmgen/proto/btc/tx/completed.py +++ b/mmgen/proto/btc/tx/completed.py @@ -24,7 +24,7 @@ class Completed(Base, TxBase.Completed): if o := self.data_output: try: return o.data.decode() - except: + except UnicodeDecodeError: pass # check signature and witness data diff --git a/mmgen/proto/eth/tx/status.py b/mmgen/proto/eth/tx/status.py index 6e50e178..4a554d7d 100755 --- a/mmgen/proto/eth/tx/status.py +++ b/mmgen/proto/eth/tx/status.py @@ -13,7 +13,7 @@ proto.eth.tx.status: Ethereum transaction status class """ from ....tx import status as TxBase -from ....util import msg, die, suf, capfirst +from ....util import msg, die, suf, capfirst, pp_fmt class Status(TxBase.Status): @@ -42,11 +42,11 @@ class Status(TxBase.Status): d = await tx.rpc.call('eth_getTransactionReceipt', '0x'+tx.coin_txid) if d and 'blockNumber' in d and d['blockNumber'] is not None: from collections import namedtuple - receipt_info = namedtuple('receipt_info', ['confs', 'exec_status']) + receipt_info = namedtuple('receipt_info', ['confs', 'exec_status', 'rx']) return receipt_info( - confs = 1 + int(await tx.rpc.call('eth_blockNumber'), 16) - int(d['blockNumber'], 16), - exec_status = int(d['status'], 16) - ) + confs = 1 + int(await tx.rpc.call('eth_blockNumber'), 16) - int(d['blockNumber'], 16), + exec_status = int(d['status'], 16), + rx = d) if await is_in_mempool(): msg( @@ -56,6 +56,9 @@ class Status(TxBase.Status): if usr_req: ret = await is_in_wallet() + if tx.cfg.verbose: + from ....color import cyan + msg('{}\n{}'.format(cyan('TRANSACTION RECEIPT'), pp_fmt(ret.rx))) if ret: if tx.txobj['data']: cd = capfirst(tx.contract_desc) diff --git a/mmgen/swap/proto/thorchain/thornode.py b/mmgen/swap/proto/thorchain/thornode.py index 07b170b4..d67d8735 100755 --- a/mmgen/swap/proto/thorchain/thornode.py +++ b/mmgen/swap/proto/thorchain/thornode.py @@ -56,7 +56,7 @@ class Thornode: def __init__(self, tx, amt): self.tx = tx - self.in_amt = UniAmt(str(amt)) + self.in_amt = UniAmt(f'{amt:.8f}') self.rpc = ThornodeRPCClient(tx) def get_quote(self): @@ -80,7 +80,7 @@ class Thornode: tx = self.tx in_coin = tx.proto.coin out_coin = tx.recv_proto.coin - in_amt = UniAmt(str(self.in_amt)) + in_amt = self.in_amt out_amt = UniAmt(int(d['expected_amount_out']), from_unit='satoshi') gas_unit = d['gas_rate_units'] @@ -110,7 +110,7 @@ class Thornode: _amount_in_label = 'Amount in:' if deduct_est_fee: if gas_unit in gas_unit_data: - in_amt -= UniAmt(str(get_estimated_fee())) + in_amt -= UniAmt(f'{get_estimated_fee():.8f}') out_amt *= (in_amt / self.in_amt) _amount_in_label = 'Amount in (estimated):' else: diff --git a/mmgen/tw/view.py b/mmgen/tw/view.py index d09aa571..f991ee1e 100755 --- a/mmgen/tw/view.py +++ b/mmgen/tw/view.py @@ -398,7 +398,7 @@ class TwView(MMGenObject, metaclass=AsyncInit): def make_display(): - def gen_hdr(): + def gen_hdr(spc): Blue, Green = (blue, green) if color else (nocolor, nocolor) Yes, No, All = (green('yes'), red('no'), yellow('all')) if color else ('yes', 'no', 'all') @@ -410,12 +410,12 @@ class TwView(MMGenObject, metaclass=AsyncInit): yield '{} (sort order: {}){}'.format( self.hdr_lbl.upper(), Blue(sort_info), - ' ' * (self.cols - len(f'{self.hdr_lbl} (sort order: {sort_info})'))) + spc * (self.cols - len(f'{self.hdr_lbl} (sort order: {sort_info})'))) if self.filters: yield 'Filters: {}{}'.format( ' '.join(map(fmt_filter, self.filters)), - ' ' * len(self.filters)) + spc * len(self.filters)) yield 'Network: {}'.format(Green( self.proto.coin + ' ' + self.proto.chain_name.upper())) @@ -429,7 +429,7 @@ class TwView(MMGenObject, metaclass=AsyncInit): yield from getattr(self, dt.subhdr_fmt_method)(cw, color) - yield ' ' * self.term_width + yield spc * self.term_width if data and dt.colhdr_fmt_method: col_hdr = getattr(self, dt.colhdr_fmt_method)(cw, hdr_fs, color) @@ -456,7 +456,7 @@ class TwView(MMGenObject, metaclass=AsyncInit): cw = hdr_fs = fs = None return ( - tuple(gen_hdr()), + tuple(gen_hdr(spc='' if line_processing == 'print' else ' ')), tuple( get_body(getattr(self, dt.fmt_method)) if data else [(nocolor, yellow)[color](self.nodata_msg.ljust(self.term_width))]) diff --git a/mmgen/tx/info.py b/mmgen/tx/info.py index 22412242..21663ec4 100755 --- a/mmgen/tx/info.py +++ b/mmgen/tx/info.py @@ -74,8 +74,9 @@ class TxInfo: if tx.is_swap: from ..swap.proto.thorchain.memo import Memo, proto_name - if Memo.is_partial_memo(tx.data_output.data): - p = Memo.parse(tx.data_output.data) + text = tx.data_output.data.decode() + if Memo.is_partial_memo(text): + p = Memo.parse(text) yield ' {} {}\n'.format(magenta('DEX Protocol:'), blue(proto_name)) yield ' Swap: {}\n'.format(orange(f'{tx.proto.coin} => {p.asset}')) yield ' Dest: {}{}\n'.format( diff --git a/mmgen/tx/new_swap.py b/mmgen/tx/new_swap.py index 7021d85a..dcf2104d 100755 --- a/mmgen/tx/new_swap.py +++ b/mmgen/tx/new_swap.py @@ -55,12 +55,12 @@ class NewSwap(New): proto, arg, self.get_addrdata_from_files(proto, addrfiles), - await TwAddrData(self.cfg, proto, twctl=None)) # TODO: twctl required for Ethereum + await TwAddrData(self.cfg, proto)) if pa.addr: await self.warn_addr_used(proto, pa, desc) return ret(proto.coin, proto.network, pa.addr, pa.mmid) - full_desc = '{} on the {} {} network'.format(desc, proto.coin, proto.network) + full_desc = f'{desc} on the {proto.coin} {proto.network} network' res = await self.get_autochg_addr(proto, arg, exclude=[], desc=full_desc, all_addrtypes=not arg) self.confirm_autoselected_addr(res.twmmid, full_desc) return ret(proto.coin, proto.network, res.addr, res.twmmid) @@ -92,6 +92,7 @@ class NewSwap(New): # arg 2: amt if is_coin_amt(self.proto, arg): + UniAmt(arg) # throw exception on decimal overflow args.send_amt = self.proto.coin_amt(arg) arg = get_arg() diff --git a/pyproject.toml b/pyproject.toml index 46ced4f1..e61d0e00 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,8 @@ mixin-class-rgx = """.*[Mm]ixin|\ ^(Hilite|InitErrors|DummyWIF|\ cfg_file|cfg_file_sample|\ MoneroMMGenFile|keygen_base|xmr_signable|\ - CmdTestShared)$""" + CmdTestShared|CmdTestSwapMethods|HTTPD|\ + RPC|TxProxyClient|Contract)$""" ignored-classes = [ # ignored for no-member, otherwise checked "optparse.Values", @@ -133,5 +134,5 @@ ignored-classes = [ # ignored for no-member, otherwise checked "Opts", "Help", "FFI_override", - "RPC", + "CmdGroupMgr", ] diff --git a/test/cmdtest_d/ct_regtest.py b/test/cmdtest_d/ct_regtest.py index 4c0897c6..78737b22 100755 --- a/test/cmdtest_d/ct_regtest.py +++ b/test/cmdtest_d/ct_regtest.py @@ -64,7 +64,7 @@ pat_date_time = r'\b\d\d\d\d-\d\d-\d\d\s+\d\d:\d\d\b' dfl_wcls = get_wallet_cls('mmgen') -tx_fee = rtFundAmt = rtFee = rtBals = rtBals_gb = rtBobOp3 = rtAmts = None # ruff +tx_fee = rtFundAmt = rtFee = rtBals = rtBals_gb = rtBobOp3 = rtAmts = {} # ruff, pylint rt_data = { 'tx_fee': {'btc':'0.0001', 'bch':'0.001', 'ltc':'0.01'}, diff --git a/test/cmdtest_d/httpd/thornode.py b/test/cmdtest_d/httpd/thornode.py index 7c770496..28f6ed35 100755 --- a/test/cmdtest_d/httpd/thornode.py +++ b/test/cmdtest_d/httpd/thornode.py @@ -24,7 +24,9 @@ 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 } +prices = {'BTC': 97000, 'LTC': 115, 'BCH': 330} +gas_rate_units = {'BTC': 'satsperbyte'} +recommended_gas_rate = {'BTC': '6'} data_template = { 'inbound_address': None, @@ -84,5 +86,7 @@ class ThornodeServer(HTTPD): 'expected_amount_out': str(out_amt.to_unit('satoshi')), 'expiry': int(time.time()) + (10 * 60), 'inbound_address': addr, + 'gas_rate_units': gas_rate_units[send_proto.base_proto_coin], + 'recommended_gas_rate': recommended_gas_rate[send_proto.base_proto_coin], } return json.dumps(data).encode() diff --git a/test/cmdtest_d/runner.py b/test/cmdtest_d/runner.py index 9561d7b2..88b8fca0 100755 --- a/test/cmdtest_d/runner.py +++ b/test/cmdtest_d/runner.py @@ -148,7 +148,8 @@ class CmdTestRunner: passthru_opts = ( self.passthru_opts if not no_passthru_opts else [] if no_passthru_opts is True else - [o for o in self.passthru_opts if o[2:].split('=')[0] not in no_passthru_opts]) + [o for o in self.passthru_opts + if o[2:].split('=')[0].replace('-','_') not in no_passthru_opts]) args = ( self.pre_args + @@ -289,7 +290,8 @@ class CmdTestRunner: self.passthru_opts = ['--{}{}'.format( k.replace('_', '-'), '' if self.cfg._uopts[k] is True else '=' + self.cfg._uopts[k] - ) for k in self.cfg._uopts if k in self.tg.base_passthru_opts + self.tg.passthru_opts] + ) for k in self.cfg._uopts + if self.cfg._uopts[k] and k in self.tg.base_passthru_opts + self.tg.passthru_opts] if self.cfg.resuming: rc = self.cfg.resume or self.cfg.resume_after