From fc55750cd23a625e1726641788254869e9d18f3f Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Fri, 18 Oct 2024 10:32:03 +0000 Subject: [PATCH] tx, tw: whitespace, cleanups --- mmgen/amt.py | 82 ++++++++-------- mmgen/proto/btc/tw/txhistory.py | 6 +- mmgen/proto/btc/tx/base.py | 70 +++++++------- mmgen/proto/btc/tx/bump.py | 2 +- mmgen/proto/btc/tx/new.py | 20 ++-- mmgen/proto/eth/contract.py | 6 +- mmgen/proto/eth/tw/ctl.py | 4 +- mmgen/proto/eth/tx/base.py | 12 +-- mmgen/proto/eth/tx/completed.py | 4 +- mmgen/proto/eth/tx/new.py | 21 ++--- mmgen/proto/eth/tx/signed.py | 6 +- mmgen/rpc.py | 4 +- mmgen/tx/file.py | 36 +++---- mmgen/tx/new.py | 162 ++++++++++++++++---------------- test/cmdtest_py_d/ct_ethdev.py | 4 +- 15 files changed, 219 insertions(+), 220 deletions(-) diff --git a/mmgen/amt.py b/mmgen/amt.py index d83ded4a..71146b40 100755 --- a/mmgen/amt.py +++ b/mmgen/amt.py @@ -21,12 +21,12 @@ amt: MMGen CoinAmt and related classes """ from decimal import Decimal -from .objmethods import Hilite,InitErrors +from .objmethods import Hilite, InitErrors class DecimalNegateResult(Decimal): pass -class CoinAmt(Decimal,Hilite,InitErrors): # abstract class +class CoinAmt(Decimal, Hilite, InitErrors): # abstract class """ Instantiating with 'from_decimal' rounds value down to 'max_prec' precision. For addition and subtraction, operand types must match. @@ -41,28 +41,30 @@ class CoinAmt(Decimal,Hilite,InitErrors): # abstract class max_amt = None # coin supply if known, otherwise None units = () # defined unit names, e.g. ('satoshi',...) - def __new__(cls,num,from_unit=None,from_decimal=False): - if isinstance(num,cls): + def __new__(cls, num, from_unit=None, from_decimal=False): + + if isinstance(num, cls): return num + try: if from_unit: - assert from_unit in cls.units, f'{from_unit!r}: unrecognized denomination for {cls.__name__}' - assert type(num) is int,'value is not an integer' - me = Decimal.__new__(cls,num * getattr(cls,from_unit)) + assert from_unit in cls.units, f'{from_unit!r}: unrecognized coin unit for {cls.__name__}' + assert type(num) is int, 'value is not an integer' + me = Decimal.__new__(cls, num * getattr(cls, from_unit)) elif from_decimal: - assert isinstance(num,Decimal), f'number must be of type Decimal, not {type(num).__name__})' - me = Decimal.__new__(cls,num.quantize(Decimal('10') ** -cls.max_prec)) + assert isinstance(num, Decimal), f'number must be of type Decimal, not {type(num).__name__})' + me = Decimal.__new__(cls, num.quantize(Decimal('10') ** -cls.max_prec)) else: for bad_type in cls.forbidden_types: - assert not isinstance(num,bad_type), f'number is of forbidden type {bad_type.__name__}' - me = Decimal.__new__(cls,str(num)) - assert me.normalize().as_tuple()[-1] >= -cls.max_prec,'too many decimal places in coin amount' + assert not isinstance(num, bad_type), f'number is of forbidden type {bad_type.__name__}' + me = Decimal.__new__(cls, str(num)) + assert me.normalize().as_tuple()[-1] >= -cls.max_prec, 'too many decimal places in coin amount' if cls.max_amt: assert me <= cls.max_amt, f'{me}: coin amount too large (>{cls.max_amt})' - assert me >= 0,'coin amount cannot be negative' + assert me >= 0, 'coin amount cannot be negative' return me except Exception as e: - return cls.init_fail(e,num) + return cls.init_fail(e, num) def to_unit(self,unit,show_decimal=False): ret = Decimal(self) // getattr(self,unit) @@ -72,40 +74,36 @@ class CoinAmt(Decimal,Hilite,InitErrors): # abstract class return int(ret) @classmethod - def fmtc(cls,*args,**kwargs): + def fmtc(cls, *args, **kwargs): cls.method_not_implemented() - def fmt( - self, - color = False, - iwidth = 1, # width of the integer part - prec = None ): + def fmt(self, color=False, iwidth=1, prec=None): # iwidth: width of the integer part s = str(self) prec = prec or self.max_prec if '.' in s: - a,b = s.split('.',1) + a, b = s.split('.', 1) return self.colorize( a.rjust(iwidth) + '.' + b.ljust(prec)[:prec], # truncation, not rounding! - color = color ) + color = color) else: return self.colorize( s.rjust(iwidth).ljust(iwidth+prec+1), - color = color ) + color = color) - def hl(self,color=True): - return self.colorize(str(self),color=color) + def hl(self, color=True): + return self.colorize(str(self), color=color) # fancy highlighting with coin unit, enclosure, formatting - def hl2(self,color=True,unit=False,fs='{}',encl=''): + def hl2(self, color=True, unit=False, fs='{}', encl=''): res = fs.format(self) return ( encl[:-1] + self.colorize( (res.rstrip('0').rstrip('.') if '.' in res else res) + (' ' + self.coin if unit else ''), - color = color ) + color = color) + encl[1:] ) @@ -113,26 +111,26 @@ class CoinAmt(Decimal,Hilite,InitErrors): # abstract class return str(int(self)) if int(self) == self else self.normalize().__format__('f') def __repr__(self): - return "{}('{}')".format(type(self).__name__,self.__str__()) + return "{}('{}')".format(type(self).__name__, self.__str__()) - def __add__(self,other,*args,**kwargs): + def __add__(self, other, *args, **kwargs): """ we must allow other to be int(0) to use the sum() builtin """ if type(other) not in ( type(self), DecimalNegateResult ) and other != 0: raise ValueError( f'operand {other} of incorrect type ({type(other).__name__} != {type(self).__name__})') - return type(self)(Decimal.__add__(self,other,*args,**kwargs)) + return type(self)(Decimal.__add__(self, other, *args, **kwargs)) __radd__ = __add__ - def __sub__(self,other,*args,**kwargs): + def __sub__(self, other, *args, **kwargs): if type(other) is not type(self): raise ValueError( f'operand {other} of incorrect type ({type(other).__name__} != {type(self).__name__})') - return type(self)(Decimal.__sub__(self,other,*args,**kwargs)) + return type(self)(Decimal.__sub__(self, other, *args, **kwargs)) - def copy_negate(self,*args,**kwargs): + def copy_negate(self, *args, **kwargs): """ We implement this so that __add__() can check type, because: class Decimal: @@ -140,29 +138,29 @@ class CoinAmt(Decimal,Hilite,InitErrors): # abstract class ... return self.__add__(other.copy_negate(), ...) """ - return DecimalNegateResult(Decimal.copy_negate(self,*args,**kwargs)) + return DecimalNegateResult(Decimal.copy_negate(self, *args, **kwargs)) - def __mul__(self,other,*args,**kwargs): + def __mul__(self, other, *args, **kwargs): return type(self)('{:0.{p}f}'.format( - Decimal.__mul__(self,Decimal(other),*args,**kwargs), + Decimal.__mul__(self, Decimal(other), *args, **kwargs), p = self.max_prec )) __rmul__ = __mul__ - def __truediv__(self,other,*args,**kwargs): + def __truediv__(self, other, *args, **kwargs): return type(self)('{:0.{p}f}'.format( - Decimal.__truediv__(self,Decimal(other),*args,**kwargs), + Decimal.__truediv__(self, Decimal(other), *args, **kwargs), p = self.max_prec )) - def __neg__(self,*args,**kwargs): + def __neg__(self, *args, **kwargs): self.method_not_implemented() - def __floordiv__(self,*args,**kwargs): + def __floordiv__(self, *args, **kwargs): self.method_not_implemented() - def __mod__(self,*args,**kwargs): + def __mod__(self, *args, **kwargs): self.method_not_implemented() class BTCAmt(CoinAmt): @@ -195,7 +193,7 @@ class ETHAmt(CoinAmt): Gwei = Decimal('0.000000001') szabo = Decimal('0.000001') finney = Decimal('0.001') - units = ('wei','Kwei','Mwei','Gwei','szabo','finney') + units = ('wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney') def toWei(self): return int(Decimal(self) // self.wei) diff --git a/mmgen/proto/btc/tw/txhistory.py b/mmgen/proto/btc/tw/txhistory.py index 079d6ca9..4a476aa6 100755 --- a/mmgen/proto/btc/tw/txhistory.py +++ b/mmgen/proto/btc/tw/txhistory.py @@ -106,9 +106,9 @@ class BitcoinTwTransaction: 'inputs': max(len(addr) for addr in gen_all_addrs('inputs')), 'outputs': max(len(addr) for addr in gen_all_addrs('outputs')) } - self.inputs_total = total( self.vouts_info['inputs'] ) - self.outputs_total = self.proto.coin_amt( sum(i['value'] for i in self.tx['decoded']['vout']) ) - self.wallet_outputs_total = total( self.vouts_info['outputs'] ) + self.inputs_total = total(self.vouts_info['inputs']) + self.outputs_total = self.proto.coin_amt(sum(i['value'] for i in self.tx['decoded']['vout'])) + self.wallet_outputs_total = total(self.vouts_info['outputs']) self.fee = self.inputs_total - self.outputs_total self.nOutputs = len(self.tx['decoded']['vout']) self.confirmations = self.tx['confirmations'] diff --git a/mmgen/proto/btc/tx/base.py b/mmgen/proto/btc/tx/base.py index 4c73ce46..50aa6e75 100755 --- a/mmgen/proto/btc/tx/base.py +++ b/mmgen/proto/btc/tx/base.py @@ -15,23 +15,23 @@ proto.btc.tx.base: Bitcoin base transaction class from collections import namedtuple from ....tx import base as TxBase -from ....obj import MMGenList,HexStr -from ....util import msg,make_chksum_6,die,pp_fmt +from ....obj import MMGenList, HexStr +from ....util import msg, make_chksum_6, die, pp_fmt -def addr2scriptPubKey(proto,addr): +def addr2scriptPubKey(proto, addr): - def decode_addr(proto,addr): + def decode_addr(proto, addr): ap = proto.decode_addr(addr) assert ap, f'coin address {addr!r} could not be parsed' return ap.bytes.hex() return { - 'p2pkh': '76a914' + decode_addr(proto,addr) + '88ac', - 'p2sh': 'a914' + decode_addr(proto,addr) + '87', - 'bech32': proto.witness_vernum_hex + '14' + decode_addr(proto,addr) + 'p2pkh': '76a914' + decode_addr(proto, addr) + '88ac', + 'p2sh': 'a914' + decode_addr(proto, addr) + '87', + 'bech32': proto.witness_vernum_hex + '14' + decode_addr(proto, addr) }[addr.addr_fmt] -def scriptPubKey2addr(proto,s): +def scriptPubKey2addr(proto, s): if len(s) == 50 and s[:6] == '76a914' and s[-4:] == '88ac': return proto.pubhash2addr(bytes.fromhex(s[6:-4]), 'p2pkh'), 'p2pkh' elif len(s) == 46 and s[:4] == 'a914' and s[-2:] == '87': @@ -41,19 +41,19 @@ def scriptPubKey2addr(proto,s): else: raise NotImplementedError(f'Unknown scriptPubKey ({s})') -def DeserializeTX(proto,txhex): +def DeserializeTX(proto, txhex): """ Parse a serialized Bitcoin transaction For checking purposes, additionally reconstructs the serialized TX without signature """ def bytes2int(bytes_le): - return int(bytes_le[::-1].hex(),16) + return int(bytes_le[::-1].hex(), 16) def bytes2coin_amt(bytes_le): return proto.coin_amt(bytes2int(bytes_le) * proto.coin_amt.satoshi) - def bshift(n,skip=False,sub_null=False): + def bshift(n, skip=False, sub_null=False): nonlocal idx, raw_tx ret = tx[idx:idx+n] idx += n @@ -81,7 +81,7 @@ def DeserializeTX(proto,txhex): idx += vbytes_len if not skip: raw_tx += vbytes - return int(vbytes[::-1].hex(),16) + return int(vbytes[::-1].hex(), 16) def make_txid(tx_bytes): from hashlib import sha256 @@ -94,20 +94,20 @@ def DeserializeTX(proto,txhex): d = { 'version': bytes2int(bshift(4)) } if d['version'] > 0x7fffffff: # version is signed integer - die(3,f"{d['version']}: transaction version greater than maximum allowed value (int32_t)!") + die(3, f"{d['version']}: transaction version greater than maximum allowed value (int32_t)!") has_witness = tx[idx] == 0 if has_witness: - u = bshift(2,skip=True).hex() + u = bshift(2, skip=True).hex() if u != '0001': - die( 'IllegalWitnessFlagValue', f'{u!r}: Illegal value for flag in transaction!' ) + die('IllegalWitnessFlagValue', f'{u!r}: Illegal value for flag in transaction!') d['num_txins'] = readVInt() d['txins'] = MMGenList([{ 'txid': bshift(32)[::-1].hex(), 'vout': bytes2int(bshift(4)), - 'scriptSig': bshift(readVInt(skip=True),sub_null=True).hex(), + 'scriptSig': bshift(readVInt(skip=True), sub_null=True).hex(), 'nSeq': bshift(4)[::-1].hex() } for i in range(d['num_txins'])]) @@ -119,7 +119,7 @@ def DeserializeTX(proto,txhex): } for i in range(d['num_txouts'])]) for o in d['txouts']: - o['address'] = scriptPubKey2addr(proto,o['scriptPubKey'])[0] + o['address'] = scriptPubKey2addr(proto, o['scriptPubKey'])[0] if has_witness: # https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki @@ -131,21 +131,21 @@ def DeserializeTX(proto,txhex): for txin in d['txins']: if tx[idx] == 0: - bshift(1,skip=True) + bshift(1, skip=True) continue txin['witness'] = [ - bshift(readVInt(skip=True),skip=True).hex() for item in range(readVInt(skip=True)) ] + bshift(readVInt(skip=True), skip=True).hex() for item in range(readVInt(skip=True)) ] else: d['txid'] = make_txid(tx) d['witness_size'] = 0 if len(tx) - idx != 4: - die( 'TxHexParseError', 'TX hex has invalid length: {} extra bytes'.format(len(tx)-idx-4) ) + die('TxHexParseError', 'TX hex has invalid length: {} extra bytes'.format(len(tx)-idx-4)) d['locktime'] = bytes2int(bshift(4)) d['unsigned_hex'] = raw_tx.hex() - return namedtuple('deserialized_tx',list(d.keys()))(**d) + return namedtuple('deserialized_tx', list(d.keys()))(**d) class Base(TxBase.Base): rel_fee_desc = 'satoshis per byte' @@ -160,7 +160,7 @@ class Base(TxBase.Base): def sort_func(a): return ( bytes.fromhex(a.txid) - + int.to_bytes(a.vout,4,'big') ) + + int.to_bytes(a.vout, 4, 'big')) self.sort(key=sort_func) class OutputList(TxBase.Base.OutputList): @@ -168,15 +168,15 @@ class Base(TxBase.Base): def sort_bip69(self): def sort_func(a): return ( - int.to_bytes(a.amt.to_unit('satoshi'),8,'big') - + bytes.fromhex(addr2scriptPubKey(self.parent.proto,a.addr)) ) + int.to_bytes(a.amt.to_unit('satoshi'), 8, 'big') + + bytes.fromhex(addr2scriptPubKey(self.parent.proto, a.addr))) self.sort(key=sort_func) def has_segwit_inputs(self): - return any(i.mmtype in ('S','B') for i in self.inputs) + return any(i.mmtype in ('S', 'B') for i in self.inputs) def has_segwit_outputs(self): - return any(o.mmtype in ('S','B') for o in self.outputs) + return any(o.mmtype in ('S', 'B') for o in self.outputs) # https://bitcoin.stackexchange.com/questions/1195/how-to-calculate-transaction-size-before-sending # 180: uncompressed, 148: compressed @@ -217,7 +217,7 @@ class Base(TxBase.Base): def get_outputs_size(): # output bytes = amt: 8, byte_count: 1+, pk_script # pk_script bytes: p2pkh: 25, p2sh: 23, bech32: 22 - return sum({'p2pkh':34,'p2sh':32,'bech32':31}[o.addr.addr_fmt] for o in self.outputs) + return sum({'p2pkh':34, 'p2sh':32, 'bech32':31}[o.addr.addr_fmt] for o in self.outputs) # https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki # The witness is a serialization of all witness data of the transaction. Each txin is @@ -231,7 +231,7 @@ class Base(TxBase.Base): if not self.has_segwit_inputs(): return 0 wf_size = 1 + 1 + sig_size + 1 + pubkey_size_compressed # vInt vInt sig vInt pubkey = 108 - return sum((1,wf_size)[i.mmtype in ('S','B')] for i in self.inputs) + return sum((1, wf_size)[i.mmtype in ('S', 'B')] for i in self.inputs) isize = get_inputs_size() osize = get_outputs_size() @@ -250,24 +250,24 @@ class Base(TxBase.Base): self.cfg._util.dmsg( '\nData from estimate_size():\n' + f' inputs size: {isize}, outputs size: {osize}, witness size: {wsize}\n' + - f' size: {new_size}, vsize: {ret}, old_size: {old_size}' ) + f' size: {new_size}, vsize: {ret}, old_size: {old_size}') return int(ret * (self.cfg.vsize_adj or 1)) # convert absolute CoinAmt fee to sat/byte using estimated size - def fee_abs2rel(self,abs_fee,to_unit='satoshi'): + def fee_abs2rel(self, abs_fee, to_unit='satoshi'): return int( abs_fee / - getattr( self.proto.coin_amt, to_unit ) / - self.estimate_size() ) + getattr(self.proto.coin_amt, to_unit) / + self.estimate_size()) @property def deserialized(self): if not self._deserialized: - self._deserialized = DeserializeTX(self.proto,self.serialized) + self._deserialized = DeserializeTX(self.proto, self.serialized) return self._deserialized - def update_serialized(self,data): + def update_serialized(self, data): self.serialized = HexStr(data) self._deserialized = None self.check_serialized_integrity() @@ -286,7 +286,7 @@ class Base(TxBase.Base): def do_error(errmsg): die('TxHexMismatch', errmsg+'\n'+hdr) - def check_equal(desc,hexio,mmio): + def check_equal(desc, hexio, mmio): if mmio != hexio: msg('\nMMGen {d}:\n{m}\nSerialized {d}:\n{h}'.format( d = desc, diff --git a/mmgen/proto/btc/tx/bump.py b/mmgen/proto/btc/tx/bump.py index d100252a..94e731df 100755 --- a/mmgen/proto/btc/tx/bump.py +++ b/mmgen/proto/btc/tx/bump.py @@ -40,7 +40,7 @@ class Bump(Completed,New,TxBase.Bump): ret.hl(), desc, self.min_fee, - self.fee_abs2rel(self.min_fee.hl()), + self.fee_abs2rel(self.min_fee), self.rel_fee_desc, c = self.coin )) return False diff --git a/mmgen/proto/btc/tx/new.py b/mmgen/proto/btc/tx/new.py index a2907002..747d45f9 100755 --- a/mmgen/proto/btc/tx/new.py +++ b/mmgen/proto/btc/tx/new.py @@ -47,15 +47,16 @@ class New(Base,TxBase.New): fe_type = 'estimatesmartfee' except: args = self.rpc.daemon.estimatefee_args(self.rpc) - fee_per_kb = await self.rpc.call('estimatefee',*args) + fee_per_kb = await self.rpc.call('estimatefee', *args) fe_type = 'estimatefee' - return fee_per_kb,fe_type + return fee_per_kb, fe_type # given tx size, rel fee and units, return absolute fee - def fee_rel2abs(self,tx_size,units,amt,unit): + def fee_rel2abs(self, tx_size, units, amt_in_units, unit): if tx_size: - return self.proto.coin_amt(amt * tx_size * getattr(self.proto.coin_amt,units[unit])) + return self.proto.coin_amt( + amt_in_units * tx_size * getattr(self.proto.coin_amt, units[unit])) else: return None @@ -65,7 +66,7 @@ class New(Base,TxBase.New): tx_size = self.estimate_size() ret = self.proto.coin_amt( fee_per_kb * Decimal(self.cfg.fee_adjust) * tx_size / 1024, - from_decimal = True ) + from_decimal = True) if self.cfg.verbose: msg(fmt(f""" {fe_type.upper()} fee for {self.cfg.fee_estimate_confs} confirmations: {fee_per_kb} {self.coin}/kB @@ -100,9 +101,7 @@ class New(Base,TxBase.New): msg(self.no_chg_msg) self.outputs.pop(self.chg_idx) else: - self.update_output_amt( - self.chg_idx, - self.proto.coin_amt(funds_left) ) + self.update_output_amt(self.chg_idx, self.proto.coin_amt(funds_left)) def check_fee(self): fee = self.sum_inputs() - self.sum_outputs() @@ -111,10 +110,7 @@ class New(Base,TxBase.New): die( 'MaxFeeExceeded', f'Transaction fee of {fee} {c} too high! (> {self.proto.max_tx_fee} {c})' ) def final_inputs_ok_msg(self,funds_left): - return 'Transaction produces {} {} in change'.format( - self.proto.coin_amt(funds_left).hl(), - self.coin - ) + return 'Transaction produces {} {} in change'.format(self.proto.coin_amt(funds_left).hl(), self.coin) async def create_serialized(self,locktime=None,bump=None): diff --git a/mmgen/proto/eth/contract.py b/mmgen/proto/eth/contract.py index d4a392d4..091d3f56 100755 --- a/mmgen/proto/eth/contract.py +++ b/mmgen/proto/eth/contract.py @@ -41,7 +41,8 @@ class TokenCommon(MMGenObject): return CoinAddr(self.proto,parse_abi(data)[1][-40:]) def transferdata2amt(self,data): # online - return self.proto.coin_amt(int(parse_abi(data)[-1],16) * self.base_unit) + return self.proto.coin_amt( + int(parse_abi(data)[-1], 16) * self.base_unit) async def do_call(self,method_sig,method_args='',toUnit=False): data = self.create_method_id(method_sig) + method_args @@ -57,7 +58,8 @@ class TokenCommon(MMGenObject): return ret async def get_balance(self,acct_addr): - return self.proto.coin_amt(await self.do_call('balanceOf(address)',acct_addr.rjust(64,'0'),toUnit=True)) + return self.proto.coin_amt( + await self.do_call('balanceOf(address)', acct_addr.rjust(64, '0'), toUnit=True)) def strip(self,s): return ''.join([chr(b) for b in s if 32 <= b <= 127]).strip() diff --git a/mmgen/proto/eth/tw/ctl.py b/mmgen/proto/eth/tw/ctl.py index d90a3261..e2813ad3 100755 --- a/mmgen/proto/eth/tw/ctl.py +++ b/mmgen/proto/eth/tw/ctl.py @@ -82,7 +82,9 @@ class EthereumTwCtl(TwCtl): msg(f'{self.desc} upgraded successfully!') async def rpc_get_balance(self,addr): - return self.proto.coin_amt(int(await self.rpc.call('eth_getBalance','0x'+addr,'latest'),16),'wei') + return self.proto.coin_amt( + int(await self.rpc.call('eth_getBalance', '0x' + addr, 'latest'), 16), + from_unit = 'wei') @write_mode async def batch_import_address(self,args_list): diff --git a/mmgen/proto/eth/tx/base.py b/mmgen/proto/eth/tx/base.py index f74d0f9c..349eebfa 100755 --- a/mmgen/proto/eth/tx/base.py +++ b/mmgen/proto/eth/tx/base.py @@ -30,15 +30,15 @@ class Base(TxBase.Base): disable_fee_check = False # given absolute fee in ETH, return gas price in Gwei using self.gas - def fee_abs2rel(self,abs_fee,to_unit='Gwei'): - ret = self.proto.coin_amt(int(abs_fee.toWei() // self.gas.toWei()),'wei') + def fee_abs2rel(self, abs_fee, to_unit='Gwei'): + ret = self.proto.coin_amt(int(abs_fee.toWei() // self.gas.toWei()), from_unit='wei') self.cfg._util.dmsg(f'fee_abs2rel() ==> {ret} ETH') - return ret if to_unit == 'eth' else ret.to_unit(to_unit,show_decimal=True) + return ret if to_unit == 'eth' else ret.to_unit(to_unit, show_decimal=True) # given rel fee (gasPrice) in wei, return absolute fee using self.gas (Ethereum-only method) - def fee_gasPrice2abs(self,rel_fee): - assert isinstance(rel_fee,int), f'{rel_fee!r}: incorrect type for fee estimate (not an integer)' - return self.proto.coin_amt(rel_fee * self.gas.toWei(),'wei') + def fee_gasPrice2abs(self, rel_fee): + assert isinstance(rel_fee, int), f'{rel_fee!r}: incorrect type for fee estimate (not an integer)' + return self.proto.coin_amt(rel_fee * self.gas.toWei(), from_unit='wei') def is_replaceable(self): return True diff --git a/mmgen/proto/eth/tx/completed.py b/mmgen/proto/eth/tx/completed.py index d8645d9d..4b79400a 100755 --- a/mmgen/proto/eth/tx/completed.py +++ b/mmgen/proto/eth/tx/completed.py @@ -24,8 +24,8 @@ class Completed(Base,TxBase.Completed): super().__init__(*args,**kwargs) - self.gas = self.proto.coin_amt(self.dfl_gas,'wei') - self.start_gas = self.proto.coin_amt(self.dfl_start_gas,'wei') + self.gas = self.proto.coin_amt(self.dfl_gas, from_unit='wei') + self.start_gas = self.proto.coin_amt(self.dfl_start_gas, from_unit='wei') @property def send_amt(self): diff --git a/mmgen/proto/eth/tx/new.py b/mmgen/proto/eth/tx/new.py index 062a262f..8258b622 100755 --- a/mmgen/proto/eth/tx/new.py +++ b/mmgen/proto/eth/tx/new.py @@ -33,10 +33,10 @@ class New(Base,TxBase.New): super().__init__(*args,**kwargs) if self.cfg.gas: - self.gas = self.start_gas = self.proto.coin_amt(int(self.cfg.gas),'wei') + self.gas = self.start_gas = self.proto.coin_amt(int(self.cfg.gas), from_unit='wei') else: - self.gas = self.proto.coin_amt(self.dfl_gas,'wei') - self.start_gas = self.proto.coin_amt(self.dfl_start_gas,'wei') + self.gas = self.proto.coin_amt(self.dfl_gas, from_unit='wei') + self.start_gas = self.proto.coin_amt(self.dfl_start_gas, from_unit='wei') if self.cfg.contract_data: m = "'--contract-data' option may not be used with token transaction" @@ -115,18 +115,17 @@ class New(Base,TxBase.New): # get rel_fee (gas price) from network, return in native wei async def get_rel_fee_from_network(self): - return Int(await self.rpc.call('eth_gasPrice'),16),'eth_gasPrice' # ==> rel_fee,fe_type + return Int(await self.rpc.call('eth_gasPrice'),16), 'eth_gasPrice' def check_fee(self): if not self.disable_fee_check: assert self.usr_fee <= self.proto.max_tx_fee # given rel fee and units, return absolute fee using self.gas - def fee_rel2abs(self,tx_size,units,amt,unit): + def fee_rel2abs(self, tx_size, units, amt_in_units, unit): return self.proto.coin_amt( - self.proto.coin_amt(amt,units[unit]).toWei() * self.gas.toWei(), - from_unit='wei' - ) + self.proto.coin_amt(amt_in_units, units[unit]).toWei() * self.gas.toWei(), + from_unit = 'wei') # given fee estimate (gas price) in wei, return absolute fee, adjusting by self.cfg.fee_adjust def fee_est2abs(self,rel_fee,fe_type=None): @@ -174,7 +173,7 @@ class New(Base,TxBase.New): die(1,f'{addr!r}: not an MMGen ID or coin address') return ret - def final_inputs_ok_msg(self,funds_left): + def final_inputs_ok_msg(self, funds_left): chg = '0' if (self.outputs and self.outputs[0].is_chg) else funds_left return 'Transaction leaves {} {} in the sender’s account'.format( self.proto.coin_amt(chg).hl(), @@ -207,8 +206,8 @@ class TokenNew(TokenBase,New): return False return await super().precheck_sufficient_funds(inputs_sum,sel_unspent,outputs_sum) - async def get_funds_left(self,fee,outputs_sum): - return ( await self.twctl.get_eth_balance(self.inputs[0].addr) ) - fee + async def get_funds_available(self, fee, outputs_sum): + return (await self.twctl.get_eth_balance(self.inputs[0].addr)) - fee def final_inputs_ok_msg(self,funds_left): token_bal = ( diff --git a/mmgen/proto/eth/tx/signed.py b/mmgen/proto/eth/tx/signed.py index 52c406a8..2e7aa1ce 100755 --- a/mmgen/proto/eth/tx/signed.py +++ b/mmgen/proto/eth/tx/signed.py @@ -33,9 +33,9 @@ class Signed(Completed,TxBase.Signed): 'from': CoinAddr(self.proto,d['sender']), # NB: for token, 'to' is token address 'to': CoinAddr(self.proto,d['to']) if d['to'] else None, - 'amt': self.proto.coin_amt(d['value'],'wei'), - 'gasPrice': self.proto.coin_amt(d['gasprice'],'wei'), - 'startGas': self.proto.coin_amt(d['startgas'],'wei'), + 'amt': self.proto.coin_amt(d['value'], from_unit='wei'), + 'gasPrice': self.proto.coin_amt(d['gasprice'], from_unit='wei'), + 'startGas': self.proto.coin_amt(d['startgas'], from_unit='wei'), 'nonce': ETHNonce(d['nonce']), 'data': HexStr(d['data']) } if o['data'] and not o['to']: # token- or contract-creating transaction diff --git a/mmgen/rpc.py b/mmgen/rpc.py index 0974c267..00d5f894 100755 --- a/mmgen/rpc.py +++ b/mmgen/rpc.py @@ -378,7 +378,9 @@ class RPCClient(MMGenObject): wallet = wallet ) def process_http_resp(self,run_ret,batch=False,json_rpc=True): - text,status = run_ret + + text, status = run_ret + if status == 200: dmsg_rpc(' RPC RESPONSE data ==>\n{}\n',text,is_json=True) m = None diff --git a/mmgen/tx/file.py b/mmgen/tx/file.py index f8e64fa6..7a558bef 100755 --- a/mmgen/tx/file.py +++ b/mmgen/tx/file.py @@ -22,8 +22,8 @@ tx.file: Transaction file operations for the MMGen suite import os, json -from ..util import ymsg,make_chksum_6,die -from ..obj import MMGenObject,HexStr,MMGenTxID,CoinTxID,MMGenTxComment +from ..util import ymsg, make_chksum_6, die +from ..obj import MMGenObject, HexStr, MMGenTxID, CoinTxID, MMGenTxComment from ..rpc import json_encoder def json_dumps(data): @@ -51,7 +51,7 @@ def eval_io_data(tx, data, desc): 'inputs': (tx.Input, tx.InputList), 'outputs': (tx.Output, tx.OutputList), }[desc] - return io_list(parent=tx, data=[io(tx.proto,**d) for d in data]) + return io_list(parent=tx, data=[io(tx.proto, **d) for d in data]) class MMGenTxFile(MMGenObject): data_label = 'MMGenTransaction' @@ -70,7 +70,7 @@ class MMGenTxFile(MMGenObject): 'sent_timestamp': None, } - def __init__(self,tx): + def __init__(self, tx): self.tx = tx self.fmt_data = None self.filename = None @@ -127,13 +127,13 @@ class MMGenTxFile(MMGenObject): if desc == 'inputs': ymsg('Warning: transaction data appears to be in old format') import re - return literal_eval(re.sub(r"[A-Za-z]+?\(('.+?')\)",r'\1', raw_data)) + return literal_eval(re.sub(r"[A-Za-z]+?\(('.+?')\)", r'\1', raw_data)) desc = 'data' try: tx_data = data.splitlines() - assert len(tx_data) >= 5,'number of lines less than 5' - assert len(tx_data[0]) == 6,'invalid length of first line' + assert len(tx_data) >= 5, 'number of lines less than 5' + assert len(tx_data[0]) == 6, 'invalid length of first line' assert HexStr(tx_data.pop(0)) == make_chksum_6(' '.join(tx_data)), 'file data does not match checksum' if len(tx_data) == 7: @@ -142,26 +142,26 @@ class MMGenTxFile(MMGenObject): assert _ == 'Sent', 'invalid sent timestamp line' if len(tx_data) == 6: - assert len(tx_data[-1]) == 64,'invalid coin TxID length' + assert len(tx_data[-1]) == 64, 'invalid coin TxID length' desc = 'coin TxID' tx.coin_txid = CoinTxID(tx_data.pop(-1)) if len(tx_data) == 5: # rough check: allow for 4-byte utf8 characters + base58 (4 * 11 / 8 = 6 (rounded up)) - assert len(tx_data[-1]) < MMGenTxComment.max_len*6,'invalid comment length' + assert len(tx_data[-1]) < MMGenTxComment.max_len*6, 'invalid comment length' c = tx_data.pop(-1) if c != '-': desc = 'encoded comment (not base58)' from ..baseconv import baseconv comment = baseconv('b58').tobytes(c).decode() - assert comment is not False,'invalid comment' + assert comment is not False, 'invalid comment' desc = 'comment' tx.comment = MMGenTxComment(comment) desc = 'number of lines' # four required lines io_data = {} (metadata, tx.serialized, io_data['inputs'], io_data['outputs']) = tx_data - assert len(metadata) < 100,'invalid metadata length' # rough check + assert len(metadata) < 100, 'invalid metadata length' # rough check metadata = metadata.split() if metadata[-1].startswith('LT='): @@ -203,7 +203,7 @@ class MMGenTxFile(MMGenObject): desc = 'send amount in metadata' assert tx.proto.coin_amt(send_amt) == tx.send_amt, f'{send_amt} != {tx.send_amt}' except Exception as e: - die(2,f'Invalid {desc} in transaction file: {e!s}') + die(2, f'Invalid {desc} in transaction file: {e!s}') def make_filename(self): tx = self.tx @@ -213,7 +213,7 @@ class MMGenTxFile(MMGenObject): yield '-' + tx.dcoin yield f'[{tx.send_amt!s}' if tx.is_replaceable(): - yield ',{}'.format(tx.fee_abs2rel(tx.fee,to_unit=tx.fn_fee_unit)) + yield ',{}'.format(tx.fee_abs2rel(tx.fee, to_unit=tx.fn_fee_unit)) if tx.get_serialized_locktime(): yield f',tl={tx.get_serialized_locktime()}' yield ']' @@ -248,7 +248,7 @@ class MMGenTxFile(MMGenObject): if tx.comment: from ..baseconv import baseconv - lines.append(baseconv('b58').frombytes(tx.comment.encode(),tostr=True)) + lines.append(baseconv('b58').frombytes(tx.comment.encode(), tostr=True)) if tx.coin_txid: if not tx.comment: @@ -276,7 +276,7 @@ class MMGenTxFile(MMGenObject): fmt_data = {'json': format_data_json, 'legacy': format_data_legacy}[tx.file_format]() if len(fmt_data) > tx.cfg.max_tx_file_size: - die( 'MaxFileSizeExceeded', f'Transaction file size exceeds limit ({tx.cfg.max_tx_file_size} bytes)' ) + die('MaxFileSizeExceeded', f'Transaction file size exceeds limit ({tx.cfg.max_tx_file_size} bytes)') return fmt_data @@ -286,7 +286,7 @@ class MMGenTxFile(MMGenObject): ask_write = True, ask_write_default_yes = False, ask_tty = True, - ask_overwrite = True ): + ask_overwrite = True): if ask_write is False: ask_write_default_yes = True @@ -310,8 +310,8 @@ class MMGenTxFile(MMGenObject): ignore_opt_outdir = outdir) @classmethod - def get_proto(cls,cfg,filename,quiet_open=False): + def get_proto(cls, cfg, filename, quiet_open=False): from . import BaseTX tmp_tx = BaseTX(cfg=cfg) - cls(tmp_tx).parse(filename,metadata_only=True,quiet_open=quiet_open) + cls(tmp_tx).parse(filename, metadata_only=True, quiet_open=quiet_open) return tmp_tx.proto diff --git a/mmgen/tx/new.py b/mmgen/tx/new.py index fd3415b1..f4bf4bcf 100755 --- a/mmgen/tx/new.py +++ b/mmgen/tx/new.py @@ -16,9 +16,9 @@ from collections import namedtuple from .base import Base from ..cfg import gc -from ..color import pink,yellow -from ..obj import get_obj,MMGenList -from ..util import msg,fmt,die,suf,remove_dups,get_extension +from ..color import pink, yellow +from ..obj import get_obj, MMGenList +from ..util import msg, fmt, die, suf, remove_dups, get_extension from ..addr import ( is_mmgen_id, MMGenAddrType, @@ -29,7 +29,7 @@ from ..addr import ( is_addrlist_id ) -def mmaddr2coinaddr(cfg,mmaddr,ad_w,ad_f,proto): +def mmaddr2coinaddr(cfg, mmaddr, ad_w, ad_f, proto): def wmsg(k): messages = { @@ -49,7 +49,7 @@ def mmaddr2coinaddr(cfg,mmaddr,ad_w,ad_f,proto): address file for it on the command line. """ } - return '\n' + fmt(messages[k],indent=' ') + return '\n' + fmt(messages[k], indent=' ') # assume mmaddr has already been checked coin_addr = ad_w.mmaddr2coinaddr(mmaddr) @@ -60,15 +60,15 @@ def mmaddr2coinaddr(cfg,mmaddr,ad_w,ad_f,proto): if coin_addr: msg(wmsg('addr_in_addrfile_only')) from ..ui import keypress_confirm - if not (cfg.yes or keypress_confirm( cfg, 'Continue anyway?' )): + if not (cfg.yes or keypress_confirm(cfg, 'Continue anyway?')): import sys sys.exit(1) else: - die(2,wmsg('addr_not_found')) + die(2, wmsg('addr_not_found')) else: - die(2,wmsg('addr_not_found_no_addrfile')) + die(2, wmsg('addr_not_found_no_addrfile')) - return CoinAddr(proto,coin_addr) + return CoinAddr(proto, coin_addr) class New(Base): @@ -81,32 +81,32 @@ class New(Base): """ chg_autoselected = False - def update_output_amt(self,idx,amt): + def update_output_amt(self, idx, amt): o = self.outputs[idx]._asdict() o['amt'] = amt - self.outputs[idx] = self.Output(self.proto,**o) + self.outputs[idx] = self.Output(self.proto, **o) - def add_mmaddrs_to_outputs(self,ad_w,ad_f): + def add_mmaddrs_to_outputs(self, ad_w, ad_f): a = [e.addr for e in self.outputs] d = ad_w.make_reverse_dict(a) if ad_f: d.update(ad_f.make_reverse_dict(a)) for e in self.outputs: if e.addr and e.addr in d: - e.mmid,f = d[e.addr] + e.mmid, f = d[e.addr] if f: e.comment = f - def check_dup_addrs(self,io_str): - assert io_str in ('inputs','outputs') - addrs = [e.addr for e in getattr(self,io_str)] + def check_dup_addrs(self, io_str): + assert io_str in ('inputs', 'outputs') + addrs = [e.addr for e in getattr(self, io_str)] if len(addrs) != len(set(addrs)): - die(2,f'{addrs}: duplicate address in transaction {io_str}') + die(2, f'{addrs}: duplicate address in transaction {io_str}') # given tx size and absolute fee or fee spec, return absolute fee # relative fee is N+ - def feespec2abs(self,fee_arg,tx_size): - fee = get_obj(self.proto.coin_amt,num=fee_arg,silent=True) + def feespec2abs(self, fee_arg, tx_size): + fee = get_obj(self.proto.coin_amt, num=fee_arg, silent=True) if fee: return fee else: @@ -114,66 +114,66 @@ class New(Base): units = {u[0]:u for u in self.proto.coin_amt.units} pat = re.compile(r'([1-9][0-9]*)({})'.format('|'.join(units))) if pat.match(fee_arg): - amt,unit = pat.match(fee_arg).groups() - return self.fee_rel2abs(tx_size,units,int(amt),unit) + amt, unit = pat.match(fee_arg).groups() + return self.fee_rel2abs(tx_size, units, int(amt), unit) return False - def get_usr_fee_interactive(self,fee=None,desc='Starting'): + def get_usr_fee_interactive(self, fee=None, desc='Starting'): abs_fee = None from ..ui import line_input while True: if fee: - abs_fee = self.convert_and_check_fee(fee,desc) + abs_fee = self.convert_and_check_fee(fee, desc) if abs_fee: prompt = '{a} TX fee{b}: {c}{d} {e} ({f} {g})\n'.format( - a = desc, - b = (f' (after {self.cfg.fee_adjust:.2f}X adjustment)' + a = desc, + b = (f' (after {self.cfg.fee_adjust:.2f}X adjustment)' if self.cfg.fee_adjust != 1 and desc.startswith('Network-estimated') else ''), - c = ('','≈')[self.fee_is_approximate], - d = abs_fee.hl(), - e = self.coin, - f = pink(str(self.fee_abs2rel(abs_fee))), - g = self.rel_fee_disp) + c = ('', '≈')[self.fee_is_approximate], + d = abs_fee.hl(), + e = self.coin, + f = pink(str(self.fee_abs2rel(abs_fee))), + g = self.rel_fee_disp) from ..ui import keypress_confirm - if self.cfg.yes or keypress_confirm( self.cfg, prompt+'OK?', default_yes=True ): + if self.cfg.yes or keypress_confirm(self.cfg, prompt+'OK?', default_yes=True): if self.cfg.yes: msg(prompt) return abs_fee - fee = line_input( self.cfg, self.usr_fee_prompt ) + fee = line_input(self.cfg, self.usr_fee_prompt) desc = 'User-selected' # we don't know fee yet, so perform preliminary check with fee == 0 - async def precheck_sufficient_funds(self,inputs_sum,sel_unspent,outputs_sum): + async def precheck_sufficient_funds(self, inputs_sum, sel_unspent, outputs_sum): if self.twuo.total < outputs_sum: - msg(self.msg_wallet_low_coin.format(outputs_sum-inputs_sum,self.dcoin)) + msg(self.msg_wallet_low_coin.format(outputs_sum-inputs_sum, self.dcoin)) return False if inputs_sum < outputs_sum: - msg(self.msg_low_coin.format(outputs_sum-inputs_sum,self.dcoin)) + msg(self.msg_low_coin.format(outputs_sum-inputs_sum, self.dcoin)) return False return True - async def get_fee_from_user(self,have_estimate_fail=[]): + async def get_fee_from_user(self, have_estimate_fail=[]): if self.cfg.fee: desc = 'User-selected' start_fee = self.cfg.fee else: desc = self.network_estimated_fee_label - fee_per_kb,fe_type = await self.get_rel_fee_from_network() + fee_per_kb, fe_type = await self.get_rel_fee_from_network() if fee_per_kb < 0: if not have_estimate_fail: - msg(self.fee_fail_fs.format(c=self.cfg.fee_estimate_confs,t=fe_type)) + msg(self.fee_fail_fs.format(c=self.cfg.fee_estimate_confs, t=fe_type)) have_estimate_fail.append(True) start_fee = None else: - start_fee = self.fee_est2abs(fee_per_kb,fe_type) + start_fee = self.fee_est2abs(fee_per_kb, fe_type) - return self.get_usr_fee_interactive(start_fee,desc=desc) + return self.get_usr_fee_interactive(start_fee, desc=desc) - def add_output(self,coinaddr,amt,is_chg=None): - self.outputs.append(self.Output(self.proto,addr=coinaddr,amt=amt,is_chg=is_chg)) + def add_output(self, coinaddr, amt, is_chg=None): + self.outputs.append(self.Output(self.proto, addr=coinaddr, amt=amt, is_chg=is_chg)) def parse_cmd_arg(self, arg_in, ad_f, ad_w): @@ -195,7 +195,7 @@ class New(Base): return _pa(arg, mmid, coin_addr, amt) - async def process_cmd_args(self,cmd_args,ad_f,ad_w): + async def process_cmd_args(self, cmd_args, ad_f, ad_w): async def get_autochg_addr(arg, parsed_args): from ..tw.addresses import TwAddresses @@ -212,7 +212,7 @@ class New(Base): if res: return res - die(2,'Tracking wallet contains no {t}addresses {d} {a!r}'.format( + die(2, 'Tracking wallet contains no {t}addresses {d} {a!r}'.format( t = '' if res is None else 'unused ', d = desc, a = arg)) @@ -245,8 +245,8 @@ class New(Base): if not self.outputs: die(2, 'At least one output must be specified on the command line') - async def get_outputs_from_cmdline(self,cmd_args): - from ..addrdata import AddrData,TwAddrData + async def get_outputs_from_cmdline(self, cmd_args): + from ..addrdata import AddrData, TwAddrData from ..addrlist import AddrList from ..addrfile import AddrFile addrfiles = remove_dups( @@ -264,13 +264,13 @@ class New(Base): from ..fileutil import check_infile for addrfile in addrfiles: check_infile(addrfile) - ad_f.add(AddrList( self.cfg, self.proto, addrfile )) + ad_f.add(AddrList(self.cfg, self.proto, addrfile)) - ad_w = await TwAddrData(self.cfg,self.proto,twctl=self.twctl) + ad_w = await TwAddrData(self.cfg, self.proto, twctl=self.twctl) - await self.process_cmd_args(cmd_args,ad_f,ad_w) + await self.process_cmd_args(cmd_args, ad_f, ad_w) - self.add_mmaddrs_to_outputs(ad_w,ad_f) + self.add_mmaddrs_to_outputs(ad_w, ad_f) self.check_dup_addrs('outputs') if self.chg_output is not None: @@ -279,19 +279,19 @@ class New(Base): elif len(self.outputs) > 1: await self.warn_chg_addr_used(self.chg_output) - def confirm_autoselected_addr(self,chg): + def confirm_autoselected_addr(self, chg): from ..ui import keypress_confirm if not keypress_confirm( self.cfg, 'Using {a} as {b} address. OK?'.format( a = chg.mmid.hl(), - b = 'single output' if len(self.outputs) == 1 else 'change' ), - default_yes = True ): - die(1,'Exiting at user request') + b = 'single output' if len(self.outputs) == 1 else 'change'), + default_yes = True): + die(1, 'Exiting at user request') - async def warn_chg_addr_used(self,chg): + async def warn_chg_addr_used(self, chg): from ..tw.addresses import TwAddresses - if (await TwAddresses(self.cfg,self.proto,get_data=True)).is_used(chg.addr): + if (await TwAddresses(self.cfg, self.proto, get_data=True)).is_used(chg.addr): from ..ui import keypress_confirm if not keypress_confirm( self.cfg, @@ -302,24 +302,24 @@ class New(Base): d = yellow('Address reuse harms your privacy and security. Continue anyway? (y/N): ') ), complete_prompt = True, - default_yes = False ): - die(1,'Exiting at user request') + default_yes = False): + die(1, 'Exiting at user request') # inputs methods - def select_unspent(self,unspent): + def select_unspent(self, unspent): prompt = 'Enter a range or space-separated list of outputs to spend: ' from ..ui import line_input while True: - reply = line_input( self.cfg, prompt ).strip() + reply = line_input(self.cfg, prompt).strip() if reply: from ..addrlist import AddrIdxList - selected = get_obj(AddrIdxList, fmt_str=','.join(reply.split()) ) + selected = get_obj(AddrIdxList, fmt_str=','.join(reply.split())) if selected: if selected[-1] <= len(unspent): return selected msg(f'Unspent output number must be <= {len(unspent)}') - def select_unspent_cmdline(self,unspent): + def select_unspent_cmdline(self, unspent): def idx2num(idx): uo = unspent[idx] @@ -329,42 +329,42 @@ class New(Base): def get_uo_nums(): for addr in self.cfg.inputs.split(','): - if is_mmgen_id(self.proto,addr): + if is_mmgen_id(self.proto, addr): attr = 'twmmid' - elif is_coin_addr(self.proto,addr): + elif is_coin_addr(self.proto, addr): attr = 'addr' else: - die(1,f'{addr!r}: not an MMGen ID or {self.coin} address') + die(1, f'{addr!r}: not an MMGen ID or {self.coin} address') found = False - for idx,us in enumerate(unspent): - if getattr(us,attr) == addr: + for idx, us in enumerate(unspent): + if getattr(us, attr) == addr: yield idx2num(idx) found = True if not found: - die(1,f'{addr!r}: address not found in tracking wallet') + die(1, f'{addr!r}: address not found in tracking wallet') return set(get_uo_nums()) # silently discard duplicates - def copy_inputs_from_tw(self,tw_unspent_data): + def copy_inputs_from_tw(self, tw_unspent_data): def gen_inputs(): for d in tw_unspent_data: i = self.Input( self.proto, - **{attr:getattr(d,attr) for attr in d.__dict__ if attr in self.Input.tw_copy_attrs} ) + **{attr:getattr(d, attr) for attr in d.__dict__ if attr in self.Input.tw_copy_attrs}) if d.twmmid.type == 'mmgen': i.mmid = d.twmmid # twmmid -> mmid yield i - self.inputs = type(self.inputs)(self,list(gen_inputs())) + self.inputs = type(self.inputs)(self, list(gen_inputs())) - def warn_insufficient_funds(self,funds_left): - msg(self.msg_low_coin.format(self.proto.coin_amt(-funds_left).hl(),self.coin)) + def warn_insufficient_funds(self, funds_left): + msg(self.msg_low_coin.format(self.proto.coin_amt(-funds_left).hl(), self.coin)) - async def get_funds_left(self,fee,outputs_sum): + async def get_funds_available(self, fee, outputs_sum): return self.sum_inputs() - outputs_sum - fee - async def get_inputs_from_user(self,outputs_sum): + async def get_inputs_from_user(self, outputs_sum): while True: us_f = self.select_unspent_cmdline if self.cfg.inputs else self.select_unspent @@ -374,28 +374,28 @@ class New(Base): sel_unspent = MMGenList(self.twuo.data[i-1] for i in sel_nums) inputs_sum = sum(s.amt for s in sel_unspent) - if not await self.precheck_sufficient_funds(inputs_sum,sel_unspent,outputs_sum): + if not await self.precheck_sufficient_funds(inputs_sum, sel_unspent, outputs_sum): continue self.copy_inputs_from_tw(sel_unspent) # makes self.inputs self.usr_fee = await self.get_fee_from_user() - funds_left = await self.get_funds_left(self.usr_fee,outputs_sum) + funds_left = await self.get_funds_available(self.usr_fee,outputs_sum) if funds_left >= 0: p = self.final_inputs_ok_msg(funds_left) from ..ui import keypress_confirm - if self.cfg.yes or keypress_confirm( self.cfg, p+'. OK?', default_yes=True ): + if self.cfg.yes or keypress_confirm(self.cfg, p+'. OK?', default_yes=True): if self.cfg.yes: msg(p) return funds_left else: self.warn_insufficient_funds(funds_left) - async def create(self,cmd_args,locktime=None,do_info=False,caller='txcreate'): + async def create(self, cmd_args, locktime=None, do_info=False, caller='txcreate'): - assert isinstance( locktime, (int,type(None)) ), 'locktime must be of type int' + assert isinstance(locktime, (int, type(None))), 'locktime must be of type int' from ..tw.unspent import TwUnspentOutputs @@ -404,7 +404,7 @@ class New(Base): twuo_addrs = await self.get_input_addrs_from_cmdline() - self.twuo = await TwUnspentOutputs(self.cfg,self.proto,minconf=self.cfg.minconf,addrs=twuo_addrs) + self.twuo = await TwUnspentOutputs(self.cfg, self.proto, minconf=self.cfg.minconf, addrs=twuo_addrs) await self.twuo.get_data() if not do_info: diff --git a/test/cmdtest_py_d/ct_ethdev.py b/test/cmdtest_py_d/ct_ethdev.py index 00670c6c..e40c5063 100755 --- a/test/cmdtest_py_d/ct_ethdev.py +++ b/test/cmdtest_py_d/ct_ethdev.py @@ -1067,8 +1067,8 @@ class CmdTestEthdev(CmdTestBase,CmdTestShared): usr_addrs[i], amt, dfl_devkey, - start_gas = self.proto.coin_amt(60000,'wei'), - gasPrice = self.proto.coin_amt(8,'Gwei') ) + start_gas = self.proto.coin_amt(60000, from_unit='wei'), + gasPrice = self.proto.coin_amt(8, from_unit='Gwei')) if (await self.get_tx_receipt(txid)).status == 0: die(2,'Transfer of token funds failed. Aborting')