Browse Source

tx, tw: whitespace, cleanups

The MMGen Project 5 months ago
parent
commit
fc55750cd2

+ 40 - 42
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)

+ 3 - 3
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']

+ 35 - 35
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,

+ 1 - 1
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

+ 8 - 12
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):
 

+ 4 - 2
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()

+ 3 - 1
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):

+ 6 - 6
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

+ 2 - 2
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):

+ 10 - 11
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 = (

+ 3 - 3
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

+ 3 - 1
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

+ 18 - 18
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

+ 81 - 81
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+<first letter of unit name>
-	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:

+ 2 - 2
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')