Browse Source

whitespace: proto.eth (plus cleanup)

The MMGen Project 1 year ago
parent
commit
6346c1d11a

+ 3 - 3
mmgen/proto/eth/addrdata.py

@@ -31,12 +31,12 @@ class EthereumTwAddrData(TwAddrData):
 		"""
 		"""
 	}
 	}
 
 
-	async def get_tw_data(self,twctl=None):
+	async def get_tw_data(self, twctl=None):
 		from ...tw.ctl import TwCtl
 		from ...tw.ctl import TwCtl
 		self.cfg._util.vmsg('Getting address data from tracking wallet')
 		self.cfg._util.vmsg('Getting address data from tracking wallet')
-		twctl = (twctl or await TwCtl(self.cfg,self.proto)).mmid_ordered_dict
+		twctl = (twctl or await TwCtl(self.cfg, self.proto)).mmid_ordered_dict
 		# emulate the output of RPC 'listaccounts' and 'getaddressesbyaccount'
 		# emulate the output of RPC 'listaccounts' and 'getaddressesbyaccount'
-		return [(mmid+' '+d['comment'],[d['addr']]) for mmid,d in list(twctl.items())]
+		return [(mmid+' '+d['comment'], [d['addr']]) for mmid, d in list(twctl.items())]
 
 
 class EthereumTokenTwAddrData(EthereumTwAddrData):
 class EthereumTokenTwAddrData(EthereumTwAddrData):
 	pass
 	pass

+ 36 - 36
mmgen/proto/eth/contract.py

@@ -24,46 +24,46 @@ from decimal import Decimal
 from . import rlp
 from . import rlp
 
 
 from . import erigon_sleep
 from . import erigon_sleep
-from ...util import msg,pp_msg,die
+from ...util import msg, pp_msg, die
 from ...base_obj import AsyncInit
 from ...base_obj import AsyncInit
-from ...obj import MMGenObject,CoinTxID
-from ...addr import CoinAddr,TokenAddr
+from ...obj import MMGenObject, CoinTxID
+from ...addr import CoinAddr, TokenAddr
 
 
 def parse_abi(s):
 def parse_abi(s):
 	return [s[:8]] + [s[8+x*64:8+(x+1)*64] for x in range(len(s[8:])//64)]
 	return [s[:8]] + [s[8+x*64:8+(x+1)*64] for x in range(len(s[8:])//64)]
 
 
 class TokenCommon(MMGenObject):
 class TokenCommon(MMGenObject):
 
 
-	def create_method_id(self,sig):
+	def create_method_id(self, sig):
 		return self.keccak_256(sig.encode()).hexdigest()[:8]
 		return self.keccak_256(sig.encode()).hexdigest()[:8]
 
 
-	def transferdata2sendaddr(self,data): # online
-		return CoinAddr(self.proto,parse_abi(data)[1][-40:])
+	def transferdata2sendaddr(self, data): # online
+		return CoinAddr(self.proto, parse_abi(data)[1][-40:])
 
 
-	def transferdata2amt(self,data): # online
+	def transferdata2amt(self, data): # online
 		return self.proto.coin_amt(
 		return self.proto.coin_amt(
 			int(parse_abi(data)[-1], 16) * self.base_unit,
 			int(parse_abi(data)[-1], 16) * self.base_unit,
 			from_decimal = True)
 			from_decimal = True)
 
 
-	async def do_call(self,method_sig,method_args='',toUnit=False):
+	async def do_call(self, method_sig, method_args='', toUnit=False):
 		data = self.create_method_id(method_sig) + method_args
 		data = self.create_method_id(method_sig) + method_args
 		if self.cfg.debug:
 		if self.cfg.debug:
 			msg('ETH_CALL {}:  {}'.format(
 			msg('ETH_CALL {}:  {}'.format(
 				method_sig,
 				method_sig,
-				'\n  '.join(parse_abi(data)) ))
-		ret = await self.rpc.call('eth_call',{ 'to': '0x'+self.addr, 'data': '0x'+data },'pending')
+				'\n  '.join(parse_abi(data))))
+		ret = await self.rpc.call('eth_call', {'to': '0x'+self.addr, 'data': '0x'+data}, 'pending')
 		await erigon_sleep(self)
 		await erigon_sleep(self)
 		if toUnit:
 		if toUnit:
-			return int(ret,16) * self.base_unit
+			return int(ret, 16) * self.base_unit
 		else:
 		else:
 			return ret
 			return ret
 
 
-	async def get_balance(self,acct_addr):
+	async def get_balance(self, acct_addr):
 		return self.proto.coin_amt(
 		return self.proto.coin_amt(
 			await self.do_call('balanceOf(address)', acct_addr.rjust(64, '0'), toUnit=True),
 			await self.do_call('balanceOf(address)', acct_addr.rjust(64, '0'), toUnit=True),
 			from_decimal = True)
 			from_decimal = True)
 
 
-	def strip(self,s):
+	def strip(self, s):
 		return ''.join([chr(b) for b in s if 32 <= b <= 127]).strip()
 		return ''.join([chr(b) for b in s if 32 <= b <= 127]).strip()
 
 
 	async def get_name(self):
 	async def get_name(self):
@@ -76,13 +76,13 @@ class TokenCommon(MMGenObject):
 		ret = await self.do_call('decimals()')
 		ret = await self.do_call('decimals()')
 		try:
 		try:
 			assert ret[:2] == '0x'
 			assert ret[:2] == '0x'
-			return int(ret,16)
+			return int(ret, 16)
 		except:
 		except:
 			msg(f'RPC call to decimals() failed (returned {ret!r})')
 			msg(f'RPC call to decimals() failed (returned {ret!r})')
 			return None
 			return None
 
 
 	async def get_total_supply(self):
 	async def get_total_supply(self):
-		return await self.do_call('totalSupply()',toUnit=True)
+		return await self.do_call('totalSupply()', toUnit=True)
 
 
 	async def info(self):
 	async def info(self):
 		return ('{:15}{}\n' * 5).format(
 		return ('{:15}{}\n' * 5).format(
@@ -90,10 +90,10 @@ class TokenCommon(MMGenObject):
 			'token symbol:',  await self.get_symbol(),
 			'token symbol:',  await self.get_symbol(),
 			'token name:',    await self.get_name(),
 			'token name:',    await self.get_name(),
 			'decimals:',      self.decimals,
 			'decimals:',      self.decimals,
-			'total supply:',  await self.get_total_supply() )
+			'total supply:',  await self.get_total_supply())
 
 
 	async def code(self):
 	async def code(self):
-		return (await self.rpc.call('eth_getCode','0x'+self.addr))[2:]
+		return (await self.rpc.call('eth_getCode', '0x'+self.addr))[2:]
 
 
 	def create_data(
 	def create_data(
 			self,
 			self,
@@ -101,8 +101,8 @@ class TokenCommon(MMGenObject):
 			amt,
 			amt,
 			method_sig = 'transfer(address,uint256)'):
 			method_sig = 'transfer(address,uint256)'):
 		from_arg = ''
 		from_arg = ''
-		to_arg = to_addr.rjust(64,'0')
-		amt_arg = '{:064x}'.format( int(amt / self.base_unit) )
+		to_arg = to_addr.rjust(64, '0')
+		amt_arg = '{:064x}'.format(int(amt / self.base_unit))
 		return self.create_method_id(method_sig) + from_arg + to_arg + amt_arg
 		return self.create_method_id(method_sig) + from_arg + to_arg + amt_arg
 
 
 	def make_tx_in(
 	def make_tx_in(
@@ -125,24 +125,24 @@ class TokenCommon(MMGenObject):
 			'nonce':    nonce,
 			'nonce':    nonce,
 			'data':     bytes.fromhex(data)}
 			'data':     bytes.fromhex(data)}
 
 
-	async def txsign(self,tx_in,key,from_addr,chain_id=None):
+	async def txsign(self, tx_in, key, from_addr, chain_id=None):
 
 
 		from .pyethereum.transactions import Transaction
 		from .pyethereum.transactions import Transaction
 
 
 		if chain_id is None:
 		if chain_id is None:
 			res = await self.rpc.call('eth_chainId')
 			res = await self.rpc.call('eth_chainId')
-			chain_id = None if res is None else int(res,16)
+			chain_id = None if res is None else int(res, 16)
 
 
-		tx = Transaction(**tx_in).sign(key,chain_id)
+		tx = Transaction(**tx_in).sign(key, chain_id)
 
 
 		if tx.sender.hex() != from_addr:
 		if tx.sender.hex() != from_addr:
-			die(3,f'Sender address {from_addr!r} does not match address of key {tx.sender.hex()!r}!')
+			die(3, f'Sender address {from_addr!r} does not match address of key {tx.sender.hex()!r}!')
 
 
 		if self.cfg.debug:
 		if self.cfg.debug:
 			msg('TOKEN DATA:')
 			msg('TOKEN DATA:')
 			pp_msg(tx.to_dict())
 			pp_msg(tx.to_dict())
 			msg('PARSED ABI DATA:\n  {}'.format(
 			msg('PARSED ABI DATA:\n  {}'.format(
-				'\n  '.join(parse_abi(tx.data.hex())) ))
+				'\n  '.join(parse_abi(tx.data.hex()))))
 
 
 		return (
 		return (
 			rlp.encode(tx).hex(),
 			rlp.encode(tx).hex(),
@@ -151,8 +151,8 @@ class TokenCommon(MMGenObject):
 
 
 # The following are used for token deployment only:
 # The following are used for token deployment only:
 
 
-	async def txsend(self,txhex):
-		return (await self.rpc.call('eth_sendRawTransaction','0x'+txhex)).replace('0x','',1)
+	async def txsend(self, txhex):
+		return (await self.rpc.call('eth_sendRawTransaction', '0x'+txhex)).replace('0x', '', 1)
 
 
 	async def transfer(
 	async def transfer(
 			self,
 			self,
@@ -168,35 +168,35 @@ class TokenCommon(MMGenObject):
 				amt,
 				amt,
 				start_gas,
 				start_gas,
 				gasPrice,
 				gasPrice,
-				nonce = int(await self.rpc.call('eth_getTransactionCount','0x'+from_addr,'pending'),16),
+				nonce = int(await self.rpc.call('eth_getTransactionCount', '0x'+from_addr, 'pending'), 16),
 				method_sig = method_sig)
 				method_sig = method_sig)
-		txhex,_ = await self.txsign(tx_in,key,from_addr)
+		txhex, _ = await self.txsign(tx_in, key, from_addr)
 		return await self.txsend(txhex)
 		return await self.txsend(txhex)
 
 
 class Token(TokenCommon):
 class Token(TokenCommon):
 
 
-	def __init__(self,cfg,proto,addr,decimals,rpc=None):
+	def __init__(self, cfg, proto, addr, decimals, rpc=None):
 		if type(self).__name__ == 'Token':
 		if type(self).__name__ == 'Token':
 			from ...util2 import get_keccak
 			from ...util2 import get_keccak
 			self.keccak_256 = get_keccak(cfg)
 			self.keccak_256 = get_keccak(cfg)
 		self.cfg = cfg
 		self.cfg = cfg
 		self.proto = proto
 		self.proto = proto
-		self.addr = TokenAddr(proto,addr)
-		assert isinstance(decimals,int),f'decimals param must be int instance, not {type(decimals)}'
+		self.addr = TokenAddr(proto, addr)
+		assert isinstance(decimals, int), f'decimals param must be int instance, not {type(decimals)}'
 		self.decimals = decimals
 		self.decimals = decimals
 		self.base_unit = Decimal('10') ** -self.decimals
 		self.base_unit = Decimal('10') ** -self.decimals
 		self.rpc = rpc
 		self.rpc = rpc
 
 
-class ResolvedToken(TokenCommon,metaclass=AsyncInit):
+class ResolvedToken(TokenCommon, metaclass=AsyncInit):
 
 
-	async def __init__(self,cfg,proto,rpc,addr):
+	async def __init__(self, cfg, proto, rpc, addr):
 		from ...util2 import get_keccak
 		from ...util2 import get_keccak
 		self.keccak_256 = get_keccak(cfg)
 		self.keccak_256 = get_keccak(cfg)
 		self.cfg = cfg
 		self.cfg = cfg
 		self.proto = proto
 		self.proto = proto
 		self.rpc = rpc
 		self.rpc = rpc
-		self.addr = TokenAddr(proto,addr)
+		self.addr = TokenAddr(proto, addr)
 		decimals = await self.get_decimals() # requires self.addr!
 		decimals = await self.get_decimals() # requires self.addr!
 		if not decimals:
 		if not decimals:
-			die( 'TokenNotInBlockchain', f'Token {addr!r} not in blockchain' )
-		Token.__init__(self,cfg,proto,addr,decimals,rpc)
+			die('TokenNotInBlockchain', f'Token {addr!r} not in blockchain')
+		Token.__init__(self, cfg, proto, addr, decimals, rpc)

+ 31 - 31
mmgen/proto/eth/daemon.py

@@ -15,29 +15,29 @@ proto.eth.daemon: Ethereum base protocol daemon classes
 import os
 import os
 
 
 from ...cfg import gc
 from ...cfg import gc
-from ...util import list_gen,get_subclasses
-from ...daemon import CoinDaemon,RPCDaemon,_nw,_dd
+from ...util import list_gen, get_subclasses
+from ...daemon import CoinDaemon, RPCDaemon, _nw, _dd
 
 
 class ethereum_daemon(CoinDaemon):
 class ethereum_daemon(CoinDaemon):
-	chain_subdirs = _nw('ethereum','goerli','DevelopmentChain')
+	chain_subdirs = _nw('ethereum', 'goerli', 'DevelopmentChain')
 	base_rpc_port = 8545  # same for all networks!
 	base_rpc_port = 8545  # same for all networks!
 	base_authrpc_port = 8551 # same for all networks!
 	base_authrpc_port = 8551 # same for all networks!
 	base_p2p_port = 30303 # same for all networks!
 	base_p2p_port = 30303 # same for all networks!
 	daemon_port_offset = 100
 	daemon_port_offset = 100
-	network_port_offsets = _nw(0,10,20)
+	network_port_offsets = _nw(0, 10, 20)
 
 
-	def __init__(self,*args,test_suite=False,**kwargs):
+	def __init__(self, *args, test_suite=False, **kwargs):
 
 
-		if not hasattr(self,'all_daemons'):
-			ethereum_daemon.all_daemons = get_subclasses(ethereum_daemon,names=True)
+		if not hasattr(self, 'all_daemons'):
+			ethereum_daemon.all_daemons = get_subclasses(ethereum_daemon, names=True)
 
 
 		daemon_idx_offset = (
 		daemon_idx_offset = (
 			self.all_daemons.index(self.id+'_daemon') * self.daemon_port_offset
 			self.all_daemons.index(self.id+'_daemon') * self.daemon_port_offset
-			if test_suite else 0 )
+			if test_suite else 0)
 
 
-		self.port_offset = daemon_idx_offset + getattr(self.network_port_offsets,self.network)
+		self.port_offset = daemon_idx_offset + getattr(self.network_port_offsets, self.network)
 
 
-		super().__init__( *args, test_suite=test_suite, **kwargs )
+		super().__init__(*args, test_suite=test_suite, **kwargs)
 
 
 	def get_rpc_port(self):
 	def get_rpc_port(self):
 		return self.base_rpc_port + self.port_offset
 		return self.base_rpc_port + self.port_offset
@@ -54,7 +54,7 @@ class ethereum_daemon(CoinDaemon):
 		return os.path.join(
 		return os.path.join(
 			self.logdir,
 			self.logdir,
 			self.id,
 			self.id,
-			getattr(self.chain_subdirs,self.network) )
+			getattr(self.chain_subdirs, self.network))
 
 
 class openethereum_daemon(ethereum_daemon):
 class openethereum_daemon(ethereum_daemon):
 	daemon_data = _dd('OpenEthereum', 3003005, '3.3.5')
 	daemon_data = _dd('OpenEthereum', 3003005, '3.3.5')
@@ -62,9 +62,9 @@ class openethereum_daemon(ethereum_daemon):
 	exec_fn = 'openethereum'
 	exec_fn = 'openethereum'
 	cfg_file = 'parity.conf'
 	cfg_file = 'parity.conf'
 	datadirs = {
 	datadirs = {
-		'linux': [gc.home_dir,'.local','share','io.parity.ethereum'],
+		'linux': [gc.home_dir, '.local', 'share', 'io.parity.ethereum'],
 		'darwin': [gc.home_dir, 'Library', 'Application Support', 'io.parity.ethereum'],
 		'darwin': [gc.home_dir, 'Library', 'Application Support', 'io.parity.ethereum'],
-		'win32': [os.getenv('LOCALAPPDATA'),'Parity','Ethereum']
+		'win32': [os.getenv('LOCALAPPDATA'), 'Parity', 'Ethereum']
 	}
 	}
 
 
 	def init_subclass(self):
 	def init_subclass(self):
@@ -102,20 +102,20 @@ class geth_daemon(ethereum_daemon):
 	exec_fn = 'geth'
 	exec_fn = 'geth'
 	use_pidfile = False
 	use_pidfile = False
 	use_threads = True
 	use_threads = True
-	avail_opts = ('no_daemonize','online')
+	avail_opts = ('no_daemonize', 'online')
 	version_info_arg = 'version'
 	version_info_arg = 'version'
 	datadirs = {
 	datadirs = {
-		'linux': [gc.home_dir,'.ethereum','geth'],
+		'linux': [gc.home_dir, '.ethereum', 'geth'],
 		'darwin': [gc.home_dir, 'Library', 'Ethereum', 'geth'],
 		'darwin': [gc.home_dir, 'Library', 'Ethereum', 'geth'],
-		'win32': [os.getenv('LOCALAPPDATA'),'Geth'] # FIXME
+		'win32': [os.getenv('LOCALAPPDATA'), 'Geth'] # FIXME
 	}
 	}
 
 
 	def init_subclass(self):
 	def init_subclass(self):
 
 
 		def have_authrpc():
 		def have_authrpc():
-			from subprocess import run,PIPE
+			from subprocess import run, PIPE
 			try:
 			try:
-				return b'authrpc' in run(['geth','help'],check=True,stdout=PIPE).stdout
+				return b'authrpc' in run(['geth', 'help'], check=True, stdout=PIPE).stdout
 			except:
 			except:
 				return False
 				return False
 
 
@@ -138,12 +138,12 @@ class erigon_daemon(geth_daemon):
 	daemon_data = _dd('Erigon', 2022099099, '2022.99.99')
 	daemon_data = _dd('Erigon', 2022099099, '2022.99.99')
 	version_pat = r'erigon/(\d+)\.(\d+)\.(\d+)'
 	version_pat = r'erigon/(\d+)\.(\d+)\.(\d+)'
 	exec_fn = 'erigon'
 	exec_fn = 'erigon'
-	private_ports = _nw(9090,9091,9092) # testnet and regtest are non-standard
-	torrent_ports = _nw(42069,42070,None) # testnet is non-standard
+	private_ports = _nw(9090, 9091, 9092) # testnet and regtest are non-standard
+	torrent_ports = _nw(42069, 42070, None) # testnet is non-standard
 	version_info_arg = '--version'
 	version_info_arg = '--version'
 	datadirs = {
 	datadirs = {
-		'linux': [gc.home_dir,'.local','share','erigon'],
-		'win32': [os.getenv('LOCALAPPDATA'),'Erigon'] # FIXME
+		'linux': [gc.home_dir, '.local', 'share', 'erigon'],
+		'win32': [os.getenv('LOCALAPPDATA'), 'Erigon'] # FIXME
 	}
 	}
 
 
 	def init_subclass(self):
 	def init_subclass(self):
@@ -169,21 +169,21 @@ class erigon_daemon(geth_daemon):
 			rpc_port     = self.rpc_port,
 			rpc_port     = self.rpc_port,
 			private_port = self.private_port,
 			private_port = self.private_port,
 			test_suite   = self.test_suite,
 			test_suite   = self.test_suite,
-			datadir      = self.datadir )
+			datadir      = self.datadir)
 
 
-	def start(self,quiet=False,silent=False):
-		super().start(quiet=quiet,silent=silent)
+	def start(self, quiet=False, silent=False):
+		super().start(quiet=quiet, silent=silent)
 		self.rpc_d.debug = self.debug
 		self.rpc_d.debug = self.debug
-		return self.rpc_d.start(quiet=quiet,silent=silent)
+		return self.rpc_d.start(quiet=quiet, silent=silent)
 
 
-	def stop(self,quiet=False,silent=False):
+	def stop(self, quiet=False, silent=False):
 		self.rpc_d.debug = self.debug
 		self.rpc_d.debug = self.debug
-		self.rpc_d.stop(quiet=quiet,silent=silent)
-		return super().stop(quiet=quiet,silent=silent)
+		self.rpc_d.stop(quiet=quiet, silent=silent)
+		return super().stop(quiet=quiet, silent=silent)
 
 
 	@property
 	@property
 	def start_cmds(self):
 	def start_cmds(self):
-		return [self.start_cmd,self.rpc_d.start_cmd]
+		return [self.start_cmd, self.rpc_d.start_cmd]
 
 
 class erigon_rpcdaemon(RPCDaemon):
 class erigon_rpcdaemon(RPCDaemon):
 
 
@@ -193,7 +193,7 @@ class erigon_rpcdaemon(RPCDaemon):
 	use_pidfile = False
 	use_pidfile = False
 	use_threads = True
 	use_threads = True
 
 
-	def __init__(self,cfg,proto,rpc_port,private_port,test_suite,datadir):
+	def __init__(self, cfg, proto, rpc_port, private_port, test_suite, datadir):
 
 
 		self.proto = proto
 		self.proto = proto
 		self.test_suite = test_suite
 		self.test_suite = test_suite

+ 11 - 10
mmgen/proto/eth/misc.py

@@ -14,7 +14,7 @@ proto.eth.misc: miscellaneous utilities for Ethereum base protocol
 
 
 from ...util2 import get_keccak
 from ...util2 import get_keccak
 
 
-def decrypt_geth_keystore(cfg,wallet_fn,passwd,check_addr=True):
+def decrypt_geth_keystore(cfg, wallet_fn, passwd, check_addr=True):
 	"""
 	"""
 	Decrypt the encrypted private key in a Geth keystore wallet, returning the decrypted key
 	Decrypt the encrypted private key in a Geth keystore wallet, returning the decrypted key
 	"""
 	"""
@@ -33,32 +33,32 @@ def decrypt_geth_keystore(cfg,wallet_fn,passwd,check_addr=True):
 	if check_addr:
 	if check_addr:
 		from ...tool.coin import tool_cmd
 		from ...tool.coin import tool_cmd
 		from ...protocol import init_proto
 		from ...protocol import init_proto
-		t = tool_cmd( cfg=cfg, proto=init_proto(cfg,'eth') )
+		t = tool_cmd(cfg=cfg, proto=init_proto(cfg, 'eth'))
 		addr = t.wif2addr(key.hex())
 		addr = t.wif2addr(key.hex())
 		addr_chk = wallet_data['address']
 		addr_chk = wallet_data['address']
 		assert addr == addr_chk, f'incorrect address: ({addr} != {addr_chk})'
 		assert addr == addr_chk, f'incorrect address: ({addr} != {addr_chk})'
 
 
 	return key
 	return key
 
 
-def hash_message(cfg,message,msghash_type):
+def hash_message(cfg, message, msghash_type):
 	return get_keccak(cfg)(
 	return get_keccak(cfg)(
 		{
 		{
 			'raw': message,
 			'raw': message,
-			'eth_sign': '\x19Ethereum Signed Message:\n{}{}'.format( len(message), message ),
+			'eth_sign': '\x19Ethereum Signed Message:\n{}{}'.format(len(message), message),
 		}[msghash_type].encode()
 		}[msghash_type].encode()
 	).digest()
 	).digest()
 
 
-def ec_sign_message_with_privkey(cfg,message,key,msghash_type):
+def ec_sign_message_with_privkey(cfg, message, key, msghash_type):
 	"""
 	"""
 	Sign an arbitrary string with an Ethereum private key, returning the signature
 	Sign an arbitrary string with an Ethereum private key, returning the signature
 
 
 	Conforms to the standard defined by the Geth `eth_sign` JSON-RPC call
 	Conforms to the standard defined by the Geth `eth_sign` JSON-RPC call
 	"""
 	"""
 	from py_ecc.secp256k1 import ecdsa_raw_sign
 	from py_ecc.secp256k1 import ecdsa_raw_sign
-	v,r,s = ecdsa_raw_sign( hash_message(cfg,message,msghash_type), key )
-	return '{:064x}{:064x}{:02x}'.format(r,s,v)
+	v, r, s = ecdsa_raw_sign(hash_message(cfg, message, msghash_type), key)
+	return '{:064x}{:064x}{:02x}'.format(r, s, v)
 
 
-def ec_recover_pubkey(cfg,message,sig,msghash_type):
+def ec_recover_pubkey(cfg, message, sig, msghash_type):
 	"""
 	"""
 	Given a message and signature, recover the public key associated with the private key
 	Given a message and signature, recover the public key associated with the private key
 	used to make the signature
 	used to make the signature
@@ -66,7 +66,8 @@ def ec_recover_pubkey(cfg,message,sig,msghash_type):
 	Conforms to the standard defined by the Geth `eth_sign` JSON-RPC call
 	Conforms to the standard defined by the Geth `eth_sign` JSON-RPC call
 	"""
 	"""
 	from py_ecc.secp256k1 import ecdsa_raw_recover
 	from py_ecc.secp256k1 import ecdsa_raw_recover
-	r,s,v = ( sig[:64], sig[64:128], sig[128:] )
+	r, s, v = (sig[:64], sig[64:128], sig[128:])
 	return '{:064x}{:064x}'.format(
 	return '{:064x}{:064x}'.format(
-		*ecdsa_raw_recover( hash_message(cfg,message,msghash_type), tuple(int(hexstr,16) for hexstr in (v,r,s)) )
+		*ecdsa_raw_recover(
+			hash_message(cfg, message, msghash_type), tuple(int(hexstr, 16) for hexstr in (v, r, s)))
 	)
 	)

+ 6 - 6
mmgen/proto/eth/msg.py

@@ -18,23 +18,23 @@ class coin_msg(coin_msg):
 
 
 	include_pubhash = False
 	include_pubhash = False
 	sigdata_pfx = '0x'
 	sigdata_pfx = '0x'
-	msghash_types = ('eth_sign','raw') # first-listed is the default
+	msghash_types = ('eth_sign', 'raw') # first-listed is the default
 
 
 	class unsigned(coin_msg.unsigned):
 	class unsigned(coin_msg.unsigned):
 
 
-		async def do_sign(self,wif,message,msghash_type):
+		async def do_sign(self, wif, message, msghash_type):
 			from .misc import ec_sign_message_with_privkey
 			from .misc import ec_sign_message_with_privkey
-			return ec_sign_message_with_privkey( self.cfg, message, bytes.fromhex(wif), msghash_type )
+			return ec_sign_message_with_privkey(self.cfg, message, bytes.fromhex(wif), msghash_type)
 
 
 	class signed_online(coin_msg.signed_online):
 	class signed_online(coin_msg.signed_online):
 
 
-		async def do_verify(self,addr,sig,message,msghash_type):
+		async def do_verify(self, addr, sig, message, msghash_type):
 			from ...tool.coin import tool_cmd
 			from ...tool.coin import tool_cmd
 			from .misc import ec_recover_pubkey
 			from .misc import ec_recover_pubkey
 			return tool_cmd(
 			return tool_cmd(
 				self.cfg,
 				self.cfg,
 				proto = self.proto).pubhex2addr(
 				proto = self.proto).pubhex2addr(
-					ec_recover_pubkey( self.cfg, message, sig, msghash_type )) == addr
+					ec_recover_pubkey(self.cfg, message, sig, msghash_type)) == addr
 
 
-	class exported_sigs(coin_msg.exported_sigs,signed_online):
+	class exported_sigs(coin_msg.exported_sigs, signed_online):
 		pass
 		pass

+ 8 - 8
mmgen/proto/eth/params.py

@@ -12,13 +12,13 @@
 proto.eth.params: Ethereum protocol
 proto.eth.params: Ethereum protocol
 """
 """
 
 
-from ...protocol import CoinProtocol,_nw,decoded_addr
+from ...protocol import CoinProtocol, _nw, decoded_addr
 from ...addr import CoinAddr
 from ...addr import CoinAddr
-from ...util import is_hex_str_lc,Msg
+from ...util import is_hex_str_lc, Msg
 
 
-class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Secp256k1):
+class mainnet(CoinProtocol.DummyWIF, CoinProtocol.Secp256k1):
 
 
-	network_names = _nw('mainnet','testnet','devnet')
+	network_names = _nw('mainnet', 'testnet', 'devnet')
 	addr_len      = 20
 	addr_len      = 20
 	mmtypes       = ('E',)
 	mmtypes       = ('E',)
 	dfl_mmtype    = 'E'
 	dfl_mmtype    = 'E'
@@ -27,7 +27,7 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Secp256k1):
 
 
 	coin_amt      = 'ETHAmt'
 	coin_amt      = 'ETHAmt'
 	max_tx_fee    = '0.005'
 	max_tx_fee    = '0.005'
-	chain_names   = ['ethereum','foundation']
+	chain_names   = ['ethereum', 'foundation']
 	sign_mode     = 'standalone'
 	sign_mode     = 'standalone'
 	caps          = ('token',)
 	caps          = ('token',)
 	mmcaps        = ('rpc', 'rpc_init', 'tw', 'msg')
 	mmcaps        = ('rpc', 'rpc_init', 'tw', 'msg')
@@ -63,9 +63,9 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Secp256k1):
 			Msg(f'Invalid address: {addr}')
 			Msg(f'Invalid address: {addr}')
 		return False
 		return False
 
 
-	def checksummed_addr(self,addr):
+	def checksummed_addr(self, addr):
 		h = self.keccak_256(addr.encode()).digest().hex()
 		h = self.keccak_256(addr.encode()).digest().hex()
-		return ''.join(addr[i].upper() if int(h[i],16) > 7 else addr[i] for i in range(len(addr)))
+		return ''.join(addr[i].upper() if int(h[i], 16) > 7 else addr[i] for i in range(len(addr)))
 
 
 	def pubhash2addr(self, pubhash, addr_type):
 	def pubhash2addr(self, pubhash, addr_type):
 		assert len(pubhash) == 20, f'{len(pubhash)}: invalid length for {self.name} pubkey hash'
 		assert len(pubhash) == 20, f'{len(pubhash)}: invalid length for {self.name} pubkey hash'
@@ -74,7 +74,7 @@ class mainnet(CoinProtocol.DummyWIF,CoinProtocol.Secp256k1):
 		return CoinAddr(self, pubhash.hex())
 		return CoinAddr(self, pubhash.hex())
 
 
 class testnet(mainnet):
 class testnet(mainnet):
-	chain_names = ['kovan','goerli','rinkeby']
+	chain_names = ['kovan', 'goerli', 'rinkeby']
 
 
 class regtest(testnet):
 class regtest(testnet):
 	chain_names = ['developmentchain']
 	chain_names = ['developmentchain']

+ 19 - 19
mmgen/proto/eth/rpc.py

@@ -16,7 +16,7 @@ import re
 
 
 from ...base_obj import AsyncInit
 from ...base_obj import AsyncInit
 from ...obj import Int
 from ...obj import Int
-from ...util import die,fmt,oneshot_warning_group
+from ...util import die, fmt, oneshot_warning_group
 from ...rpc import RPCClient
 from ...rpc import RPCClient
 
 
 class daemon_warning(oneshot_warning_group):
 class daemon_warning(oneshot_warning_group):
@@ -32,7 +32,7 @@ class daemon_warning(oneshot_warning_group):
 class CallSigs:
 class CallSigs:
 	pass
 	pass
 
 
-class EthereumRPCClient(RPCClient,metaclass=AsyncInit):
+class EthereumRPCClient(RPCClient, metaclass=AsyncInit):
 
 
 	async def __init__(
 	async def __init__(
 			self,
 			self,
@@ -44,50 +44,50 @@ class EthereumRPCClient(RPCClient,metaclass=AsyncInit):
 
 
 		self.proto = proto
 		self.proto = proto
 		self.daemon = daemon
 		self.daemon = daemon
-		self.call_sigs = getattr(CallSigs,daemon.id,None)
+		self.call_sigs = getattr(CallSigs, daemon.id, None)
 
 
 		super().__init__(
 		super().__init__(
 			cfg  = cfg,
 			cfg  = cfg,
 			host = 'localhost' if cfg.test_suite else (cfg.rpc_host or 'localhost'),
 			host = 'localhost' if cfg.test_suite else (cfg.rpc_host or 'localhost'),
-			port = daemon.rpc_port )
+			port = daemon.rpc_port)
 
 
 		await self.set_backend_async(backend)
 		await self.set_backend_async(backend)
 
 
-		vi,bh,ci = await self.gathered_call(None, (
-				('web3_clientVersion',()),
-				('eth_getBlockByNumber',('latest',False)),
-				('eth_chainId',()),
+		vi, bh, ci = await self.gathered_call(None, (
+				('web3_clientVersion', ()),
+				('eth_getBlockByNumber', ('latest', False)),
+				('eth_chainId', ()),
 			))
 			))
 
 
-		vip = re.match(self.daemon.version_pat,vi,re.ASCII)
+		vip = re.match(self.daemon.version_pat, vi, re.ASCII)
 		if not vip:
 		if not vip:
-			die(2,fmt(f"""
+			die(2, fmt(f"""
 			Aborting on daemon mismatch:
 			Aborting on daemon mismatch:
 			  Requested daemon: {self.daemon.id}
 			  Requested daemon: {self.daemon.id}
 			  Running daemon:   {vi}
 			  Running daemon:   {vi}
-			""",strip_char='\t').rstrip())
+			""", strip_char='\t').rstrip())
 
 
 		self.daemon_version = int('{:d}{:03d}{:03d}'.format(*[int(e) for e in vip.groups()]))
 		self.daemon_version = int('{:d}{:03d}{:03d}'.format(*[int(e) for e in vip.groups()]))
 		self.daemon_version_str = '{}.{}.{}'.format(*vip.groups())
 		self.daemon_version_str = '{}.{}.{}'.format(*vip.groups())
 		self.daemon_version_info = vi
 		self.daemon_version_info = vi
 
 
-		self.blockcount = int(bh['number'],16)
-		self.cur_date = int(bh['timestamp'],16)
+		self.blockcount = int(bh['number'], 16)
+		self.cur_date = int(bh['timestamp'], 16)
 
 
 		self.caps = ()
 		self.caps = ()
-		if self.daemon.id in ('parity','openethereum'):
+		if self.daemon.id in ('parity', 'openethereum'):
 			if (await self.call('parity_nodeKind'))['capability'] == 'full':
 			if (await self.call('parity_nodeKind'))['capability'] == 'full':
 				self.caps += ('full_node',)
 				self.caps += ('full_node',)
-			self.chainID = None if ci is None else Int(ci,16) # parity/oe return chainID only for dev chain
-			self.chain = (await self.call('parity_chain')).replace(' ','_').replace('_testnet','')
-		elif self.daemon.id in ('geth','erigon'):
+			self.chainID = None if ci is None else Int(ci, 16) # parity/oe return chainID only for dev chain
+			self.chain = (await self.call('parity_chain')).replace(' ', '_').replace('_testnet', '')
+		elif self.daemon.id in ('geth', 'erigon'):
 			if self.daemon.network == 'mainnet':
 			if self.daemon.network == 'mainnet':
 				daemon_warning(self.daemon.id)
 				daemon_warning(self.daemon.id)
 			self.caps += ('full_node',)
 			self.caps += ('full_node',)
-			self.chainID = Int(ci,16)
+			self.chainID = Int(ci, 16)
 			self.chain = self.proto.chain_ids[self.chainID]
 			self.chain = self.proto.chain_ids[self.chainID]
 
 
-	def make_host_path(self,wallet):
+	def make_host_path(self, wallet):
 		return ''
 		return ''
 
 
 	rpcmethods = (
 	rpcmethods = (

+ 4 - 4
mmgen/proto/eth/tw/addresses.py

@@ -16,7 +16,7 @@ from ....tw.addresses import TwAddresses
 from .view import EthereumTwView
 from .view import EthereumTwView
 from .rpc import EthereumTwRPC
 from .rpc import EthereumTwRPC
 
 
-class EthereumTwAddresses(TwAddresses,EthereumTwView,EthereumTwRPC):
+class EthereumTwAddresses(TwAddresses, EthereumTwView, EthereumTwRPC):
 
 
 	has_age = False
 	has_age = False
 	prompt_fs_in = [
 	prompt_fs_in = [
@@ -35,13 +35,13 @@ class EthereumTwAddresses(TwAddresses,EthereumTwView,EthereumTwRPC):
 		'D':'i_addr_delete',
 		'D':'i_addr_delete',
 		'v':'a_view',
 		'v':'a_view',
 		'w':'a_view_detail',
 		'w':'a_view_detail',
-		'p':'a_print_detail' }
+		'p':'a_print_detail'}
 
 
-	def get_column_widths(self,data,wide,interactive):
+	def get_column_widths(self, data, wide, interactive):
 
 
 		return self.compute_column_widths(
 		return self.compute_column_widths(
 			widths = { # fixed cols
 			widths = { # fixed cols
-				'num':  max(2,len(str(len(data)))+1),
+				'num':  max(2, len(str(len(data)))+1),
 				'mmid': max(len(d.twmmid.disp) for d in data),
 				'mmid': max(len(d.twmmid.disp) for d in data),
 				'used': 0,
 				'used': 0,
 				'amt':  self.amt_widths['amt'],
 				'amt':  self.amt_widths['amt'],

+ 4 - 4
mmgen/proto/eth/tw/bal.py

@@ -25,14 +25,14 @@ from ....tw.bal import TwGetBalance
 
 
 class EthereumTwGetBalance(TwGetBalance):
 class EthereumTwGetBalance(TwGetBalance):
 
 
-	start_labels = ('TOTAL','Non-MMGen')
+	start_labels = ('TOTAL', 'Non-MMGen')
 	conf_cols = {
 	conf_cols = {
 		'ge_minconf': 'Balance',
 		'ge_minconf': 'Balance',
 	}
 	}
 
 
-	async def __init__(self,cfg,proto,*args,**kwargs):
-		self.twctl = await TwCtl(cfg,proto,mode='w')
-		await super().__init__(cfg,proto,*args,**kwargs)
+	async def __init__(self, cfg, proto, *args, **kwargs):
+		self.twctl = await TwCtl(cfg, proto, mode='w')
+		await super().__init__(cfg, proto, *args, **kwargs)
 
 
 	async def create_data(self):
 	async def create_data(self):
 		in_data = self.twctl.mmid_ordered_dict
 		in_data = self.twctl.mmid_ordered_dict

+ 41 - 41
mmgen/proto/eth/tw/ctl.py

@@ -20,11 +20,11 @@
 proto.eth.tw.ctl: Ethereum tracking wallet control class
 proto.eth.tw.ctl: Ethereum tracking wallet control class
 """
 """
 
 
-from ....util import msg,ymsg,die
+from ....util import msg, ymsg, die
 from ....tw.ctl import TwCtl, write_mode, label_addr_pair
 from ....tw.ctl import TwCtl, write_mode, label_addr_pair
 from ....tw.shared import TwLabel
 from ....tw.shared import TwLabel
-from ....addr import is_coin_addr,is_mmgen_id,CoinAddr
-from ..contract import Token,ResolvedToken
+from ....addr import is_coin_addr, is_mmgen_id, CoinAddr
+from ..contract import Token, ResolvedToken
 
 
 class EthereumTwCtl(TwCtl):
 class EthereumTwCtl(TwCtl):
 
 
@@ -81,43 +81,43 @@ class EthereumTwCtl(TwCtl):
 			self.force_write()
 			self.force_write()
 			msg(f'{self.desc} upgraded successfully!')
 			msg(f'{self.desc} upgraded successfully!')
 
 
-	async def rpc_get_balance(self,addr):
+	async def rpc_get_balance(self, addr):
 		return self.proto.coin_amt(
 		return self.proto.coin_amt(
 			int(await self.rpc.call('eth_getBalance', '0x' + addr, 'latest'), 16),
 			int(await self.rpc.call('eth_getBalance', '0x' + addr, 'latest'), 16),
 			from_unit = 'wei')
 			from_unit = 'wei')
 
 
 	@write_mode
 	@write_mode
-	async def batch_import_address(self,args_list):
+	async def batch_import_address(self, args_list):
 		return [await self.import_address(*a) for a in args_list]
 		return [await self.import_address(*a) for a in args_list]
 
 
-	async def rescan_addresses(self,coin_addrs):
+	async def rescan_addresses(self, coin_addrs):
 		pass
 		pass
 
 
 	@write_mode
 	@write_mode
-	async def import_address(self,addr,label,rescan=False):
+	async def import_address(self, addr, label, rescan=False):
 		r = self.data_root
 		r = self.data_root
 		if addr in r:
 		if addr in r:
 			if not r[addr]['mmid'] and label.mmid:
 			if not r[addr]['mmid'] and label.mmid:
 				msg(f'Warning: MMGen ID {label.mmid!r} was missing in tracking wallet!')
 				msg(f'Warning: MMGen ID {label.mmid!r} was missing in tracking wallet!')
 			elif r[addr]['mmid'] != label.mmid:
 			elif r[addr]['mmid'] != label.mmid:
-				die(3,'MMGen ID {label.mmid!r} does not match tracking wallet!')
-		r[addr] = { 'mmid': label.mmid, 'comment': label.comment }
+				die(3, 'MMGen ID {label.mmid!r} does not match tracking wallet!')
+		r[addr] = {'mmid': label.mmid, 'comment': label.comment}
 
 
 	@write_mode
 	@write_mode
-	async def remove_address(self,addr):
+	async def remove_address(self, addr):
 		r = self.data_root
 		r = self.data_root
 
 
-		if is_coin_addr(self.proto,addr):
+		if is_coin_addr(self.proto, addr):
 			have_match = lambda k: k == addr
 			have_match = lambda k: k == addr
-		elif is_mmgen_id(self.proto,addr):
+		elif is_mmgen_id(self.proto, addr):
 			have_match = lambda k: r[k]['mmid'] == addr
 			have_match = lambda k: r[k]['mmid'] == addr
 		else:
 		else:
-			die(1,f'{addr!r} is not an Ethereum address or MMGen ID')
+			die(1, f'{addr!r} is not an Ethereum address or MMGen ID')
 
 
 		for k in r:
 		for k in r:
 			if have_match(k):
 			if have_match(k):
 				# return the addr resolved to mmid if possible
 				# return the addr resolved to mmid if possible
-				ret = r[k]['mmid'] if is_mmgen_id(self.proto,r[k]['mmid']) else addr
+				ret = r[k]['mmid'] if is_mmgen_id(self.proto, r[k]['mmid']) else addr
 				del r[k]
 				del r[k]
 				self.write()
 				self.write()
 				return ret
 				return ret
@@ -125,8 +125,8 @@ class EthereumTwCtl(TwCtl):
 		return None
 		return None
 
 
 	@write_mode
 	@write_mode
-	async def set_label(self,coinaddr,lbl):
-		for addr,d in list(self.data_root.items()):
+	async def set_label(self, coinaddr, lbl):
+		for addr, d in list(self.data_root.items()):
 			if addr == coinaddr:
 			if addr == coinaddr:
 				d['comment'] = lbl.comment
 				d['comment'] = lbl.comment
 				self.write()
 				self.write()
@@ -134,32 +134,32 @@ class EthereumTwCtl(TwCtl):
 		msg(f'Address {coinaddr!r} not found in {self.data_root_desc!r} section of tracking wallet')
 		msg(f'Address {coinaddr!r} not found in {self.data_root_desc!r} section of tracking wallet')
 		return False
 		return False
 
 
-	async def addr2sym(self,req_addr):
+	async def addr2sym(self, req_addr):
 		for addr in self.data['tokens']:
 		for addr in self.data['tokens']:
 			if addr == req_addr:
 			if addr == req_addr:
 				return self.data['tokens'][addr]['params']['symbol']
 				return self.data['tokens'][addr]['params']['symbol']
 
 
-	async def sym2addr(self,sym):
+	async def sym2addr(self, sym):
 		for addr in self.data['tokens']:
 		for addr in self.data['tokens']:
 			if self.data['tokens'][addr]['params']['symbol'] == sym.upper():
 			if self.data['tokens'][addr]['params']['symbol'] == sym.upper():
 				return addr
 				return addr
 
 
-	def get_token_param(self,token,param):
+	def get_token_param(self, token, param):
 		if token in self.data['tokens']:
 		if token in self.data['tokens']:
 			return self.data['tokens'][token]['params'].get(param)
 			return self.data['tokens'][token]['params'].get(param)
 
 
 	@property
 	@property
 	def sorted_list(self):
 	def sorted_list(self):
-		return sorted(
-			[ { 'addr':x[0],
-				'mmid':x[1]['mmid'],
-				'comment':x[1]['comment'] }
-					for x in self.data_root.items() if x[0] not in ('params','coin') ],
-			key=lambda x: x['mmid'].sort_key+x['addr'] )
+		return sorted([{
+				'addr':    x[0],
+				'mmid':    x[1]['mmid'],
+				'comment': x[1]['comment']
+			} for x in self.data_root.items() if x[0] not in ('params', 'coin')],
+			key = lambda x: x['mmid'].sort_key + x['addr'])
 
 
 	@property
 	@property
 	def mmid_ordered_dict(self):
 	def mmid_ordered_dict(self):
-		return dict((x['mmid'],{'addr':x['addr'],'comment':x['comment']}) for x in self.sorted_list)
+		return dict((x['mmid'], {'addr': x['addr'], 'comment': x['comment']}) for x in self.sorted_list)
 
 
 	async def get_label_addr_pairs(self):
 	async def get_label_addr_pairs(self):
 		return [label_addr_pair(
 		return [label_addr_pair(
@@ -182,22 +182,22 @@ class EthereumTokenTwCtl(EthereumTwCtl):
 			self.conv_types(v)
 			self.conv_types(v)
 
 
 		if self.importing and token_addr:
 		if self.importing and token_addr:
-			if not is_coin_addr(proto,token_addr):
-				die( 'InvalidTokenAddress', f'{token_addr!r}: invalid token address' )
+			if not is_coin_addr(proto, token_addr):
+				die('InvalidTokenAddress', f'{token_addr!r}: invalid token address')
 		else:
 		else:
-			assert token_addr is None,'EthereumTokenTwCtl_chk1'
+			assert token_addr is None, 'EthereumTokenTwCtl_chk1'
 			token_addr = await self.sym2addr(proto.tokensym) # returns None on failure
 			token_addr = await self.sym2addr(proto.tokensym) # returns None on failure
-			if not is_coin_addr(proto,token_addr):
-				die( 'UnrecognizedTokenSymbol', f'Specified token {proto.tokensym!r} could not be resolved!' )
+			if not is_coin_addr(proto, token_addr):
+				die('UnrecognizedTokenSymbol', f'Specified token {proto.tokensym!r} could not be resolved!')
 
 
 		from ....addr import TokenAddr
 		from ....addr import TokenAddr
-		self.token = TokenAddr(proto,token_addr)
+		self.token = TokenAddr(proto, token_addr)
 
 
 		if self.token not in self.data['tokens']:
 		if self.token not in self.data['tokens']:
 			if self.importing:
 			if self.importing:
 				await self.import_token(self.token)
 				await self.import_token(self.token)
 			else:
 			else:
-				die( 'TokenNotInWallet', f'Specified token {self.token!r} not in wallet!' )
+				die('TokenNotInWallet', f'Specified token {self.token!r} not in wallet!')
 
 
 		self.decimals = self.get_param('decimals')
 		self.decimals = self.get_param('decimals')
 		self.symbol   = self.get_param('symbol')
 		self.symbol   = self.get_param('symbol')
@@ -212,29 +212,29 @@ class EthereumTokenTwCtl(EthereumTwCtl):
 	def data_root_desc(self):
 	def data_root_desc(self):
 		return 'token ' + self.get_param('symbol')
 		return 'token ' + self.get_param('symbol')
 
 
-	async def rpc_get_balance(self,addr):
-		return await Token(self.cfg,self.proto,self.token,self.decimals,self.rpc).get_balance(addr)
+	async def rpc_get_balance(self, addr):
+		return await Token(self.cfg, self.proto, self.token, self.decimals, self.rpc).get_balance(addr)
 
 
-	async def get_eth_balance(self,addr,force_rpc=False):
+	async def get_eth_balance(self, addr, force_rpc=False):
 		cache = self.cur_eth_balances
 		cache = self.cur_eth_balances
 		r = self.data['accounts']
 		r = self.data['accounts']
-		ret = None if force_rpc else self.get_cached_balance(addr,cache,r)
+		ret = None if force_rpc else self.get_cached_balance(addr, cache, r)
 		if ret is None:
 		if ret is None:
 			ret = await super().rpc_get_balance(addr)
 			ret = await super().rpc_get_balance(addr)
-			self.cache_balance(addr,ret,cache,r)
+			self.cache_balance(addr, ret, cache, r)
 		return ret
 		return ret
 
 
-	def get_param(self,param):
+	def get_param(self, param):
 		return self.data['tokens'][self.token]['params'][param]
 		return self.data['tokens'][self.token]['params'][param]
 
 
 	@write_mode
 	@write_mode
-	async def import_token(self,tokenaddr):
+	async def import_token(self, tokenaddr):
 		"""
 		"""
 		Token 'symbol' and 'decimals' values are resolved from the network by the system just
 		Token 'symbol' and 'decimals' values are resolved from the network by the system just
 		once, upon token import.  Thereafter, token address, symbol and decimals are resolved
 		once, upon token import.  Thereafter, token address, symbol and decimals are resolved
 		either from the tracking wallet (online operations) or transaction file (when signing).
 		either from the tracking wallet (online operations) or transaction file (when signing).
 		"""
 		"""
-		t = await ResolvedToken(self.cfg,self.proto,self.rpc,tokenaddr)
+		t = await ResolvedToken(self.cfg, self.proto, self.rpc, tokenaddr)
 		self.data['tokens'][tokenaddr] = {
 		self.data['tokens'][tokenaddr] = {
 			'params': {
 			'params': {
 				'symbol': await t.get_symbol(),
 				'symbol': await t.get_symbol(),

+ 28 - 28
mmgen/proto/eth/tw/json.py

@@ -20,30 +20,30 @@ class EthereumTwJSON(TwJSON):
 
 
 	class Base(TwJSON.Base):
 	class Base(TwJSON.Base):
 
 
-		def __init__(self,proto,*args,**kwargs):
+		def __init__(self, proto, *args, **kwargs):
 
 
-			self.params_keys = ['symbol','decimals']
-			self.params_tuple = namedtuple('params_tuple',self.params_keys)
+			self.params_keys = ['symbol', 'decimals']
+			self.params_tuple = namedtuple('params_tuple', self.params_keys)
 
 
-			super().__init__(proto,*args,**kwargs)
+			super().__init__(proto, *args, **kwargs)
 
 
 		@property
 		@property
 		def mappings_json(self):
 		def mappings_json(self):
 
 
 			def gen_mappings(data):
 			def gen_mappings(data):
 				for d in data:
 				for d in data:
-					yield (d.mmgen_id,d.address) if hasattr(d,'mmgen_id') else d
+					yield (d.mmgen_id, d.address) if hasattr(d, 'mmgen_id') else d
 
 
 			return self.json_dump({
 			return self.json_dump({
 				'accounts': list(gen_mappings(self.entries['accounts'])),
 				'accounts': list(gen_mappings(self.entries['accounts'])),
-				'tokens': {k:list(gen_mappings(v)) for k,v in self.entries['tokens'].items()}
+				'tokens': {k:list(gen_mappings(v)) for k, v in self.entries['tokens'].items()}
 			})
 			})
 
 
 		@property
 		@property
 		def num_entries(self):
 		def num_entries(self):
 			return len(self.entries['accounts']) + len(self.entries['tokens'])
 			return len(self.entries['accounts']) + len(self.entries['tokens'])
 
 
-	class Import(TwJSON.Import,Base):
+	class Import(TwJSON.Import, Base):
 
 
 		info_msg = """
 		info_msg = """
 			This utility will recreate a new tracking wallet from the supplied JSON dump.
 			This utility will recreate a new tracking wallet from the supplied JSON dump.
@@ -68,72 +68,72 @@ class EthereumTwJSON(TwJSON):
 					else:
 					else:
 						e = self.entry_tuple_in(*d)
 						e = self.entry_tuple_in(*d)
 						yield self.entry_tuple(
 						yield self.entry_tuple(
-							TwMMGenID(self.proto,e.mmgen_id),
+							TwMMGenID(self.proto, e.mmgen_id),
 							e.address,
 							e.address,
-							getattr(e,'amount','0'),
-							e.comment )
+							getattr(e, 'amount', '0'),
+							e.comment)
 
 
 			def gen_token_entries():
 			def gen_token_entries():
-				for token_addr,token_data in edata['tokens'].items():
+				for token_addr, token_data in edata['tokens'].items():
 					yield (
 					yield (
 						token_addr,
 						token_addr,
 						list(gen_entries(token_data)),
 						list(gen_entries(token_data)),
 					)
 					)
 
 
 			return {
 			return {
-				'accounts': list(gen_entries( edata['accounts'] )),
+				'accounts': list(gen_entries(edata['accounts'])),
 				'tokens': dict(list(gen_token_entries()))
 				'tokens': dict(list(gen_token_entries()))
 			}
 			}
 
 
-		async def do_import(self,batch):
+		async def do_import(self, batch):
 
 
 			from ....obj import TwComment
 			from ....obj import TwComment
 
 
 			def gen_data(data):
 			def gen_data(data):
 				for d in data:
 				for d in data:
-					if hasattr(d,'address'):
-						if d.amount is None:
-							yield (d.address, {'mmid':d.mmgen_id,'comment':TwComment(d.comment)})
-						else:
-							yield (d.address, {'mmid':d.mmgen_id,'comment':TwComment(d.comment),'balance':d.amount})
+					if hasattr(d, 'address'):
+						yield (
+							d.address,
+							{'mmid': d.mmgen_id, 'comment': TwComment(d.comment)}
+							| ({} if d.amount is None else {'balance': d.amount}))
 					else:
 					else:
-						yield ('params', {'symbol':d.symbol,'decimals':d.decimals})
+						yield ('params', {'symbol': d.symbol, 'decimals': d.decimals})
 
 
 			self.twctl.data = { # keys must be in correct order
 			self.twctl.data = { # keys must be in correct order
 				'coin': self.coin.upper(),
 				'coin': self.coin.upper(),
 				'network': self.network.upper(),
 				'network': self.network.upper(),
 				'accounts': dict(gen_data(self.entries['accounts'])),
 				'accounts': dict(gen_data(self.entries['accounts'])),
-				'tokens': {k:dict(gen_data(v)) for k,v in self.entries['tokens'].items()},
+				'tokens': {k:dict(gen_data(v)) for k, v in self.entries['tokens'].items()},
 			}
 			}
 			self.twctl.write(quiet=False)
 			self.twctl.write(quiet=False)
 
 
-	class Export(TwJSON.Export,Base):
+	class Export(TwJSON.Export, Base):
 
 
-		async def get_entries(self,include_amts=True):
+		async def get_entries(self, include_amts=True):
 
 
 			def gen_data(data):
 			def gen_data(data):
-				for k,v in data.items():
+				for k, v in data.items():
 					if k == 'params':
 					if k == 'params':
 						yield self.params_tuple(**v)
 						yield self.params_tuple(**v)
 					elif include_amts:
 					elif include_amts:
-						yield self.entry_tuple(TwMMGenID(self.proto,v['mmid']), k, v.get('balance'), v['comment'])
+						yield self.entry_tuple(TwMMGenID(self.proto, v['mmid']), k, v.get('balance'), v['comment'])
 					else:
 					else:
-						yield self.entry_tuple_in(TwMMGenID(self.proto,v['mmid']), k, v['comment'])
+						yield self.entry_tuple_in(TwMMGenID(self.proto, v['mmid']), k, v['comment'])
 
 
 			def gen_token_data():
 			def gen_token_data():
-				for token_addr,token_data in self.twctl.data['tokens'].items():
+				for token_addr, token_data in self.twctl.data['tokens'].items():
 					yield (
 					yield (
 						token_addr,
 						token_addr,
 						sorted(
 						sorted(
 							gen_data(token_data),
 							gen_data(token_data),
-							key = lambda x: x.mmgen_id.sort_key if hasattr(x,'mmgen_id') else '+'
+							key = lambda x: x.mmgen_id.sort_key if hasattr(x, 'mmgen_id') else '+'
 						)
 						)
 					)
 					)
 
 
 			return {
 			return {
 				'accounts': sorted(
 				'accounts': sorted(
 					gen_data(self.twctl.data['accounts']),
 					gen_data(self.twctl.data['accounts']),
-					key = lambda x: x.mmgen_id.sort_key ),
+					key = lambda x: x.mmgen_id.sort_key),
 				'tokens': dict(sorted(gen_token_data()))
 				'tokens': dict(sorted(gen_token_data()))
 			}
 			}
 
 

+ 15 - 15
mmgen/proto/eth/tw/unspent.py

@@ -25,18 +25,18 @@ from ....tw.unspent import TwUnspentOutputs
 from .view import EthereumTwView
 from .view import EthereumTwView
 
 
 # No unspent outputs with Ethereum, but naming must be consistent
 # No unspent outputs with Ethereum, but naming must be consistent
-class EthereumTwUnspentOutputs(EthereumTwView,TwUnspentOutputs):
+class EthereumTwUnspentOutputs(EthereumTwView, TwUnspentOutputs):
 
 
 	class display_type(TwUnspentOutputs.display_type):
 	class display_type(TwUnspentOutputs.display_type):
 
 
 		class squeezed(TwUnspentOutputs.display_type.squeezed):
 		class squeezed(TwUnspentOutputs.display_type.squeezed):
-			cols = ('num','addr','mmid','comment','amt','amt2')
+			cols = ('num', 'addr', 'mmid', 'comment', 'amt', 'amt2')
 
 
 		class detail(TwUnspentOutputs.display_type.detail):
 		class detail(TwUnspentOutputs.display_type.detail):
-			cols = ('num','addr','mmid','amt','amt2','comment')
+			cols = ('num', 'addr', 'mmid', 'amt', 'amt2', 'comment')
 
 
 	class MMGenTwUnspentOutput(TwUnspentOutputs.MMGenTwUnspentOutput):
 	class MMGenTwUnspentOutput(TwUnspentOutputs.MMGenTwUnspentOutput):
-		valid_attrs = {'txid','vout','amt','amt2','comment','twmmid','addr','confs','skip'}
+		valid_attrs = {'txid', 'vout', 'amt', 'amt2', 'comment', 'twmmid', 'addr', 'confs', 'skip'}
 		invalid_attrs = {'proto'}
 		invalid_attrs = {'proto'}
 
 
 	has_age = False
 	has_age = False
@@ -62,19 +62,19 @@ class EthereumTwUnspentOutputs(EthereumTwView,TwUnspentOutputs):
 		'w':'a_view_detail',
 		'w':'a_view_detail',
 		'l':'i_comment_add',
 		'l':'i_comment_add',
 		'D':'i_addr_delete',
 		'D':'i_addr_delete',
-		'R':'i_balance_refresh' }
+		'R':'i_balance_refresh'}
 
 
 	no_data_errmsg = 'No accounts in tracking wallet!'
 	no_data_errmsg = 'No accounts in tracking wallet!'
 
 
-	def get_column_widths(self,data,wide,interactive):
+	def get_column_widths(self, data, wide, interactive):
 		# min screen width: 80 cols
 		# min screen width: 80 cols
 		# num addr [mmid] [comment] amt [amt2]
 		# num addr [mmid] [comment] amt [amt2]
 		return self.compute_column_widths(
 		return self.compute_column_widths(
 			widths = { # fixed cols
 			widths = { # fixed cols
-				'num': max(2,len(str(len(data)))+1),
+				'num': max(2, len(str(len(data)))+1),
 				'mmid': max(len(d.twmmid.disp) for d in data) if self.show_mmid else 0,
 				'mmid': max(len(d.twmmid.disp) for d in data) if self.show_mmid else 0,
 				'amt': self.amt_widths['amt'],
 				'amt': self.amt_widths['amt'],
-				'amt2': self.amt_widths.get('amt2',0),
+				'amt2': self.amt_widths.get('amt2', 0),
 				'spc': (5 if self.show_mmid else 3) + self.has_amt2, # 5(3) spaces in fs
 				'spc': (5 if self.show_mmid else 3) + self.has_amt2, # 5(3) spaces in fs
 				'txid': 0,
 				'txid': 0,
 				'vout': 0,
 				'vout': 0,
@@ -95,17 +95,17 @@ class EthereumTwUnspentOutputs(EthereumTwView,TwUnspentOutputs):
 			interactive = interactive,
 			interactive = interactive,
 		)
 		)
 
 
-	def do_sort(self,key=None,reverse=False):
+	def do_sort(self, key=None, reverse=False):
 		if key == 'txid':
 		if key == 'txid':
 			return
 			return
-		super().do_sort(key=key,reverse=reverse)
+		super().do_sort(key=key, reverse=reverse)
 
 
 	async def get_rpc_data(self):
 	async def get_rpc_data(self):
 		wl = self.twctl.sorted_list
 		wl = self.twctl.sorted_list
 		if self.addrs:
 		if self.addrs:
 			wl = [d for d in wl if d['addr'] in self.addrs]
 			wl = [d for d in wl if d['addr'] in self.addrs]
 		return [{
 		return [{
-				'account': TwLabel(self.proto,d['mmid']+' '+d['comment']),
+				'account': TwLabel(self.proto, d['mmid']+' '+d['comment']),
 				'address': d['addr'],
 				'address': d['addr'],
 				'amt': await self.twctl.get_balance(d['addr']),
 				'amt': await self.twctl.get_balance(d['addr']),
 				'confirmations': 0, # TODO
 				'confirmations': 0, # TODO
@@ -115,11 +115,11 @@ class EthereumTokenTwUnspentOutputs(EthereumTwUnspentOutputs):
 
 
 	has_amt2 = True
 	has_amt2 = True
 
 
-	async def __init__(self,proto,*args,**kwargs):
-		await super().__init__(proto,*args,**kwargs)
+	async def __init__(self, proto, *args, **kwargs):
+		await super().__init__(proto, *args, **kwargs)
 		self.proto.tokensym = self.twctl.symbol
 		self.proto.tokensym = self.twctl.symbol
 
 
-	async def get_data(self,*args,**kwargs):
-		await super().get_data(*args,**kwargs)
+	async def get_data(self, *args, **kwargs):
+		await super().get_data(*args, **kwargs)
 		for e in self.data:
 		for e in self.data:
 			e.amt2 = await self.twctl.get_eth_balance(e.addr)
 			e.amt2 = await self.twctl.get_eth_balance(e.addr)

+ 5 - 5
mmgen/proto/eth/tw/view.py

@@ -24,15 +24,15 @@ class EthereumTwView(TwView):
 		'twmmid': lambda i: i.twmmid.sort_key
 		'twmmid': lambda i: i.twmmid.sort_key
 	}
 	}
 
 
-	def age_disp(self,o,age_fmt): # TODO
+	def age_disp(self, o, age_fmt): # TODO
 		pass
 		pass
 
 
-	def get_disp_prec(self,wide):
+	def get_disp_prec(self, wide):
 		return self.proto.coin_amt.max_prec if wide else 8
 		return self.proto.coin_amt.max_prec if wide else 8
 
 
-	def gen_subheader(self,cw,color):
+	def gen_subheader(self, cw, color):
 		if self.disp_prec == 8:
 		if self.disp_prec == 8:
 			yield 'Balances truncated to 8 decimal points'
 			yield 'Balances truncated to 8 decimal points'
 		if self.cfg.cached_balances:
 		if self.cfg.cached_balances:
-			from ....color import nocolor,yellow
-			yield (nocolor,yellow)[color]('WARNING: Using cached balances. These may be out of date!')
+			from ....color import nocolor, yellow
+			yield (nocolor, yellow)[color]('WARNING: Using cached balances. These may be out of date!')

+ 10 - 9
mmgen/proto/eth/tx/base.py

@@ -15,7 +15,7 @@ proto.eth.tx.base: Ethereum base transaction class
 from collections import namedtuple
 from collections import namedtuple
 
 
 from ....tx import base as TxBase
 from ....tx import base as TxBase
-from ....obj import HexStr,Int
+from ....obj import HexStr, Int
 
 
 class Base(TxBase.Base):
 class Base(TxBase.Base):
 
 
@@ -52,16 +52,17 @@ class Base(TxBase.Base):
 	def is_replaceable(self):
 	def is_replaceable(self):
 		return True
 		return True
 
 
-	async def get_receipt(self,txid):
-		rx = await self.rpc.call('eth_getTransactionReceipt','0x'+txid) # -> null if pending
+	async def get_receipt(self, txid):
+		rx = await self.rpc.call('eth_getTransactionReceipt', '0x'+txid) # -> null if pending
 		if not rx:
 		if not rx:
 			return None
 			return None
-		tx = await self.rpc.call('eth_getTransactionByHash','0x'+txid)
-		return namedtuple('exec_status',['status','gas_sent','gas_used','gas_price','contract_addr','tx','rx'])(
-			status        = Int(rx['status'],16), # zero is failure, non-zero success
-			gas_sent      = Int(tx['gas'],16),
-			gas_used      = Int(rx['gasUsed'],16),
-			gas_price     = self.proto.coin_amt(int(tx['gasPrice'],16),from_unit='wei'),
+		tx = await self.rpc.call('eth_getTransactionByHash', '0x'+txid)
+		return namedtuple('exec_status',
+				['status', 'gas_sent', 'gas_used', 'gas_price', 'contract_addr', 'tx', 'rx'])(
+			status        = Int(rx['status'], 16), # zero is failure, non-zero success
+			gas_sent      = Int(tx['gas'], 16),
+			gas_used      = Int(rx['gasUsed'], 16),
+			gas_price     = self.proto.coin_amt(int(tx['gasPrice'], 16), from_unit='wei'),
 			contract_addr = self.proto.coin_addr(rx['contractAddress'][2:]) if rx['contractAddress'] else None,
 			contract_addr = self.proto.coin_addr(rx['contractAddress'][2:]) if rx['contractAddress'] else None,
 			tx            = tx,
 			tx            = tx,
 			rx            = rx,
 			rx            = rx,

+ 5 - 5
mmgen/proto/eth/tx/bump.py

@@ -15,23 +15,23 @@ proto.eth.tx.bump: Ethereum transaction bump class
 from decimal import Decimal
 from decimal import Decimal
 
 
 from ....tx import bump as TxBase
 from ....tx import bump as TxBase
-from .completed import Completed,TokenCompleted
-from .new import New,TokenNew
+from .completed import Completed, TokenCompleted
+from .new import New, TokenNew
 
 
-class Bump(Completed,New,TxBase.Bump):
+class Bump(Completed, New, TxBase.Bump):
 	desc = 'fee-bumped transaction'
 	desc = 'fee-bumped transaction'
 
 
 	@property
 	@property
 	def min_fee(self):
 	def min_fee(self):
 		return self.fee * Decimal('1.101')
 		return self.fee * Decimal('1.101')
 
 
-	def bump_fee(self,idx,fee):
+	def bump_fee(self, idx, fee):
 		self.txobj['gasPrice'] = self.fee_abs2gas(fee)
 		self.txobj['gasPrice'] = self.fee_abs2gas(fee)
 
 
 	async def get_nonce(self):
 	async def get_nonce(self):
 		return self.txobj['nonce']
 		return self.txobj['nonce']
 
 
-class TokenBump(TokenCompleted,TokenNew,Bump):
+class TokenBump(TokenCompleted, TokenNew, Bump):
 	desc = 'fee-bumped transaction'
 	desc = 'fee-bumped transaction'
 
 
 class AutomountBump(Bump):
 class AutomountBump(Bump):

+ 5 - 5
mmgen/proto/eth/tx/completed.py

@@ -13,16 +13,16 @@ proto.eth.tx.completed: Ethereum completed transaction class
 """
 """
 
 
 from ....tx import completed as TxBase
 from ....tx import completed as TxBase
-from .base import Base,TokenBase
+from .base import Base, TokenBase
 
 
-class Completed(Base,TxBase.Completed):
+class Completed(Base, TxBase.Completed):
 	fn_fee_unit = 'Mwei'
 	fn_fee_unit = 'Mwei'
 
 
-	def __init__(self,*args,**kwargs):
+	def __init__(self, *args, **kwargs):
 
 
 		self.txobj = {}
 		self.txobj = {}
 
 
-		super().__init__(*args,**kwargs)
+		super().__init__(*args, **kwargs)
 
 
 		self.gas = self.proto.coin_amt(self.dfl_gas, from_unit='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')
 		self.start_gas = self.proto.coin_amt(self.dfl_start_gas, from_unit='wei')
@@ -54,7 +54,7 @@ class Completed(Base,TxBase.Completed):
 	def get_serialized_locktime(self):
 	def get_serialized_locktime(self):
 		return None # TODO
 		return None # TODO
 
 
-class TokenCompleted(TokenBase,Completed):
+class TokenCompleted(TokenBase, Completed):
 
 
 	@property
 	@property
 	def change(self):
 	def change(self):

+ 10 - 10
mmgen/proto/eth/tx/info.py

@@ -31,9 +31,9 @@ class TxInfo(TxInfo):
 	def format_body(self, blockcount, nonmm_str, max_mmwid, enl, terse, sort):
 	def format_body(self, blockcount, nonmm_str, max_mmwid, enl, terse, sort):
 		tx = self.tx
 		tx = self.tx
 		m = {}
 		m = {}
-		for k in ('inputs','outputs'):
-			if len(getattr(tx,k)):
-				m[k] = getattr(tx,k)[0].mmid if len(getattr(tx,k)) else ''
+		for k in ('inputs', 'outputs'):
+			if len(getattr(tx, k)):
+				m[k] = getattr(tx, k)[0].mmid if len(getattr(tx, k)) else ''
 				m[k] = ' ' + m[k].hl() if m[k] else ' ' + MMGenID.hlc(nonmm_str)
 				m[k] = ' ' + m[k].hl() if m[k] else ' ' + MMGenID.hlc(nonmm_str)
 		fs = """
 		fs = """
 			From:      {f}{f_mmid}
 			From:      {f}{f_mmid}
@@ -43,7 +43,7 @@ class TxInfo(TxInfo):
 			Start gas: {G} Kwei
 			Start gas: {G} Kwei
 			Nonce:     {n}
 			Nonce:     {n}
 			Data:      {d}
 			Data:      {d}
-		""".strip().replace('\t','')
+		""".strip().replace('\t', '')
 		t = tx.txobj
 		t = tx.txobj
 		td = t['data']
 		td = t['data']
 		to_addr = t[self.to_addr_key]
 		to_addr = t[self.to_addr_key]
@@ -52,19 +52,19 @@ class TxInfo(TxInfo):
 			t      = to_addr.hl(0) if to_addr else blue('None'),
 			t      = to_addr.hl(0) if to_addr else blue('None'),
 			a      = t['amt'].hl(),
 			a      = t['amt'].hl(),
 			n      = t['nonce'].hl(),
 			n      = t['nonce'].hl(),
-			d      = '{}... ({} bytes)'.format(td[:40],len(td)//2) if len(td) else blue('None'),
+			d      = '{}... ({} bytes)'.format(td[:40], len(td)//2) if len(td) else blue('None'),
 			c      = tx.proto.dcoin if len(tx.outputs) else '',
 			c      = tx.proto.dcoin if len(tx.outputs) else '',
 			g      = yellow(tx.pretty_fmt_fee(t['gasPrice'].to_unit('Gwei'))),
 			g      = yellow(tx.pretty_fmt_fee(t['gasPrice'].to_unit('Gwei'))),
 			G      = yellow(tx.pretty_fmt_fee(t['startGas'].to_unit('Kwei'))),
 			G      = yellow(tx.pretty_fmt_fee(t['startGas'].to_unit('Kwei'))),
 			t_mmid = m['outputs'] if len(tx.outputs) else '',
 			t_mmid = m['outputs'] if len(tx.outputs) else '',
 			f_mmid = m['inputs']) + '\n\n'
 			f_mmid = m['inputs']) + '\n\n'
 
 
-	def format_abs_fee(self,color,iwidth):
-		return self.tx.fee.fmt(color=color,iwidth=iwidth) + (' (max)' if self.tx.txobj['data'] else '')
+	def format_abs_fee(self, color, iwidth):
+		return self.tx.fee.fmt(color=color, iwidth=iwidth) + (' (max)' if self.tx.txobj['data'] else '')
 
 
 	def format_rel_fee(self):
 	def format_rel_fee(self):
 		return ' ({} of spend amount)'.format(
 		return ' ({} of spend amount)'.format(
-			pink('{:0.6f}%'.format( self.tx.fee / self.tx.send_amt * 100 ))
+			pink('{:0.6f}%'.format(self.tx.fee / self.tx.send_amt * 100))
 		)
 		)
 
 
 	def format_verbose_footer(self):
 	def format_verbose_footer(self):
@@ -80,8 +80,8 @@ class TokenTxInfo(TxInfo):
 	def format_rel_fee(self):
 	def format_rel_fee(self):
 		return ''
 		return ''
 
 
-	def format_body(self,*args,**kwargs):
+	def format_body(self, *args, **kwargs):
 		return 'Token:     {d} {c}\n{r}'.format(
 		return 'Token:     {d} {c}\n{r}'.format(
 			d = self.tx.txobj['token_addr'].hl(0),
 			d = self.tx.txobj['token_addr'].hl(0),
 			c = blue('(' + self.tx.proto.dcoin + ')'),
 			c = blue('(' + self.tx.proto.dcoin + ')'),
-			r = super().format_body(*args,**kwargs ))
+			r = super().format_body(*args, **kwargs))

+ 32 - 31
mmgen/proto/eth/tx/new.py

@@ -22,16 +22,16 @@ from ....addr import is_mmgen_id, is_coin_addr
 from ..contract import Token
 from ..contract import Token
 from .base import Base, TokenBase
 from .base import Base, TokenBase
 
 
-class New(Base,TxBase.New):
+class New(Base, TxBase.New):
 	desc = 'transaction'
 	desc = 'transaction'
 	fee_fail_fs = 'Network fee estimation failed'
 	fee_fail_fs = 'Network fee estimation failed'
 	no_chg_msg = 'Warning: Transaction leaves account with zero balance'
 	no_chg_msg = 'Warning: Transaction leaves account with zero balance'
 	usr_fee_prompt = 'Enter transaction fee or gas price: '
 	usr_fee_prompt = 'Enter transaction fee or gas price: '
 	msg_insufficient_funds = 'Account balance insufficient to fund this transaction ({} {} needed)'
 	msg_insufficient_funds = 'Account balance insufficient to fund this transaction ({} {} needed)'
 
 
-	def __init__(self,*args,**kwargs):
+	def __init__(self, *args, **kwargs):
 
 
-		super().__init__(*args,**kwargs)
+		super().__init__(*args, **kwargs)
 
 
 		if self.cfg.gas:
 		if self.cfg.gas:
 			self.gas = self.start_gas = self.proto.coin_amt(int(self.cfg.gas), from_unit='wei')
 			self.gas = self.start_gas = self.proto.coin_amt(int(self.cfg.gas), from_unit='wei')
@@ -47,7 +47,8 @@ class New(Base,TxBase.New):
 			self.disable_fee_check = True
 			self.disable_fee_check = True
 
 
 	async def get_nonce(self):
 	async def get_nonce(self):
-		return ETHNonce(int(await self.rpc.call('eth_getTransactionCount','0x'+self.inputs[0].addr,'pending'),16))
+		return ETHNonce(int(
+			await self.rpc.call('eth_getTransactionCount', '0x'+self.inputs[0].addr, 'pending'), 16))
 
 
 	async def make_txobj(self): # called by create_serialized()
 	async def make_txobj(self): # called by create_serialized()
 		self.txobj = {
 		self.txobj = {
@@ -64,22 +65,22 @@ class New(Base,TxBase.New):
 	# Instead of serializing tx data as with BTC, just create a JSON dump.
 	# Instead of serializing tx data as with BTC, just create a JSON dump.
 	# This complicates things but means we avoid using the rlp library to deserialize the data,
 	# This complicates things but means we avoid using the rlp library to deserialize the data,
 	# thus removing an attack vector
 	# thus removing an attack vector
-	async def create_serialized(self,locktime=None,bump=None):
-		assert len(self.inputs) == 1,'Transaction has more than one input!'
+	async def create_serialized(self, locktime=None, bump=None):
+		assert len(self.inputs) == 1, 'Transaction has more than one input!'
 		o_num = len(self.outputs)
 		o_num = len(self.outputs)
 		o_ok = 0 if self.usr_contract_data else 1
 		o_ok = 0 if self.usr_contract_data else 1
 		assert o_num == o_ok, f'Transaction has {o_num} output{suf(o_num)} (should have {o_ok})'
 		assert o_num == o_ok, f'Transaction has {o_num} output{suf(o_num)} (should have {o_ok})'
 		await self.make_txobj()
 		await self.make_txobj()
-		odict = {k:v if v is None else str(v) for k,v in self.txobj.items() if k != 'token_to'}
+		odict = {k:v if v is None else str(v) for k, v in self.txobj.items() if k != 'token_to'}
 		self.serialized = json.dumps(odict)
 		self.serialized = json.dumps(odict)
 		self.update_txid()
 		self.update_txid()
 
 
 	def update_txid(self):
 	def update_txid(self):
 		assert not is_hex_str(self.serialized), (
 		assert not is_hex_str(self.serialized), (
-			'update_txid() must be called only when self.serialized is not hex data' )
+			'update_txid() must be called only when self.serialized is not hex data')
 		self.txid = MMGenTxID(make_chksum_6(self.serialized).upper())
 		self.txid = MMGenTxID(make_chksum_6(self.serialized).upper())
 
 
-	async def process_cmd_args(self,cmd_args,ad_f,ad_w):
+	async def process_cmd_args(self, cmd_args, ad_f, ad_w):
 
 
 		lc = len(cmd_args)
 		lc = len(cmd_args)
 
 
@@ -96,10 +97,10 @@ class New(Base,TxBase.New):
 			amt      = self.proto.coin_amt(arg.amt or '0'),
 			amt      = self.proto.coin_amt(arg.amt or '0'),
 			is_chg   = not arg.amt)
 			is_chg   = not arg.amt)
 
 
-	def select_unspent(self,unspent):
+	def select_unspent(self, unspent):
 		from ....ui import line_input
 		from ....ui import line_input
 		while True:
 		while True:
-			reply = line_input( self.cfg, 'Enter an account to spend from: ' ).strip()
+			reply = line_input(self.cfg, 'Enter an account to spend from: ').strip()
 			if reply:
 			if reply:
 				if not is_int(reply):
 				if not is_int(reply):
 					msg('Account number must be an integer')
 					msg('Account number must be an integer')
@@ -116,7 +117,7 @@ class New(Base,TxBase.New):
 
 
 	# get rel_fee (gas price) from network, return in native wei
 	# get rel_fee (gas price) from network, return in native wei
 	async def get_rel_fee_from_network(self):
 	async def get_rel_fee_from_network(self):
-		return Int(await self.rpc.call('eth_gasPrice'),16), 'eth_gasPrice'
+		return Int(await self.rpc.call('eth_gasPrice'), 16), 'eth_gasPrice'
 
 
 	def check_fee(self):
 	def check_fee(self):
 		if not self.disable_fee_check:
 		if not self.disable_fee_check:
@@ -127,14 +128,14 @@ class New(Base,TxBase.New):
 		return self.proto.coin_amt(amt_in_units, from_unit=units[unit]) * self.gas.toWei()
 		return self.proto.coin_amt(amt_in_units, from_unit=units[unit]) * self.gas.toWei()
 
 
 	# given fee estimate (gas price) in wei, return absolute fee, adjusting by self.cfg.fee_adjust
 	# 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):
+	def fee_est2abs(self, rel_fee, fe_type=None):
 		ret = self.fee_gasPrice2abs(rel_fee) * self.cfg.fee_adjust
 		ret = self.fee_gasPrice2abs(rel_fee) * self.cfg.fee_adjust
 		if self.cfg.verbose:
 		if self.cfg.verbose:
 			msg(f'Estimated fee: {ret} ETH')
 			msg(f'Estimated fee: {ret} ETH')
 		return ret
 		return ret
 
 
-	def convert_and_check_fee(self,fee,desc):
-		abs_fee = self.feespec2abs(fee,None)
+	def convert_and_check_fee(self, fee, desc):
+		abs_fee = self.feespec2abs(fee, None)
 		if abs_fee is False:
 		if abs_fee is False:
 			return False
 			return False
 		elif not self.disable_fee_check and (abs_fee > self.proto.max_tx_fee):
 		elif not self.disable_fee_check and (abs_fee > self.proto.max_tx_fee):
@@ -142,71 +143,71 @@ class New(Base,TxBase.New):
 				abs_fee.hl(),
 				abs_fee.hl(),
 				desc,
 				desc,
 				self.proto.max_tx_fee.hl(),
 				self.proto.max_tx_fee.hl(),
-				c = self.proto.coin ))
+				c = self.proto.coin))
 			return False
 			return False
 		else:
 		else:
 			return abs_fee
 			return abs_fee
 
 
-	def update_change_output(self,funds_left):
+	def update_change_output(self, funds_left):
 		if self.outputs and self.outputs[0].is_chg:
 		if self.outputs and self.outputs[0].is_chg:
 			self.update_output_amt(0, funds_left)
 			self.update_output_amt(0, funds_left)
 
 
 	async def get_input_addrs_from_cmdline(self):
 	async def get_input_addrs_from_cmdline(self):
 		ret = []
 		ret = []
 		if self.cfg.inputs:
 		if self.cfg.inputs:
-			data_root = (await TwCtl(self.cfg,self.proto)).data_root # must create new instance here
+			data_root = (await TwCtl(self.cfg, self.proto)).data_root # must create new instance here
 			errmsg = 'Address {!r} not in tracking wallet'
 			errmsg = 'Address {!r} not in tracking wallet'
 			for addr in self.cfg.inputs.split(','):
 			for addr in self.cfg.inputs.split(','):
-				if is_mmgen_id(self.proto,addr):
+				if is_mmgen_id(self.proto, addr):
 					for waddr in data_root:
 					for waddr in data_root:
 						if data_root[waddr]['mmid'] == addr:
 						if data_root[waddr]['mmid'] == addr:
 							ret.append(waddr)
 							ret.append(waddr)
 							break
 							break
 					else:
 					else:
-						die( 'UserAddressNotInWallet', errmsg.format(addr) )
-				elif is_coin_addr(self.proto,addr):
+						die('UserAddressNotInWallet', errmsg.format(addr))
+				elif is_coin_addr(self.proto, addr):
 					if not addr in data_root:
 					if not addr in data_root:
-						die( 'UserAddressNotInWallet', errmsg.format(addr) )
+						die('UserAddressNotInWallet', errmsg.format(addr))
 					ret.append(addr)
 					ret.append(addr)
 				else:
 				else:
-					die(1,f'{addr!r}: not an MMGen ID or coin address')
+					die(1, f'{addr!r}: not an MMGen ID or coin address')
 		return ret
 		return ret
 
 
 	def final_inputs_ok_msg(self, funds_left):
 	def final_inputs_ok_msg(self, funds_left):
 		chg = self.proto.coin_amt('0') if (self.outputs and self.outputs[0].is_chg) else funds_left
 		chg = self.proto.coin_amt('0') if (self.outputs and self.outputs[0].is_chg) else funds_left
 		return 'Transaction leaves {} {} in the sender’s account'.format(chg.hl(), self.proto.coin)
 		return 'Transaction leaves {} {} in the sender’s account'.format(chg.hl(), self.proto.coin)
 
 
-class TokenNew(TokenBase,New):
+class TokenNew(TokenBase, New):
 	desc = 'transaction'
 	desc = 'transaction'
 	fee_is_approximate = True
 	fee_is_approximate = True
 
 
 	async def make_txobj(self): # called by create_serialized()
 	async def make_txobj(self): # called by create_serialized()
 		await super().make_txobj()
 		await super().make_txobj()
-		t = Token(self.cfg,self.proto,self.twctl.token,self.twctl.decimals)
+		t = Token(self.cfg, self.proto, self.twctl.token, self.twctl.decimals)
 		o = self.txobj
 		o = self.txobj
 		o['token_addr'] = t.addr
 		o['token_addr'] = t.addr
 		o['decimals'] = t.decimals
 		o['decimals'] = t.decimals
 		o['token_to'] = o['to']
 		o['token_to'] = o['to']
-		o['data'] = t.create_data(o['token_to'],o['amt'])
+		o['data'] = t.create_data(o['token_to'], o['amt'])
 
 
-	def update_change_output(self,funds_left):
+	def update_change_output(self, funds_left):
 		if self.outputs[0].is_chg:
 		if self.outputs[0].is_chg:
-			self.update_output_amt(0,self.inputs[0].amt)
+			self.update_output_amt(0, self.inputs[0].amt)
 
 
 	# token transaction, so check both eth and token balances
 	# token transaction, so check both eth and token balances
 	# TODO: add test with insufficient funds
 	# TODO: add test with insufficient funds
-	async def precheck_sufficient_funds(self,inputs_sum,sel_unspent,outputs_sum):
+	async def precheck_sufficient_funds(self, inputs_sum, sel_unspent, outputs_sum):
 		eth_bal = await self.twctl.get_eth_balance(sel_unspent[0].addr)
 		eth_bal = await self.twctl.get_eth_balance(sel_unspent[0].addr)
 		if eth_bal == 0: # we don't know the fee yet
 		if eth_bal == 0: # we don't know the fee yet
 			msg('This account has no ether to pay for the transaction fee!')
 			msg('This account has no ether to pay for the transaction fee!')
 			return False
 			return False
-		return await super().precheck_sufficient_funds(inputs_sum,sel_unspent,outputs_sum)
+		return await super().precheck_sufficient_funds(inputs_sum, sel_unspent, outputs_sum)
 
 
 	async def get_funds_available(self, fee, outputs_sum):
 	async def get_funds_available(self, fee, outputs_sum):
 		bal = await self.twctl.get_eth_balance(self.inputs[0].addr)
 		bal = await self.twctl.get_eth_balance(self.inputs[0].addr)
 		return self._funds_available(bal >= fee, bal - fee if bal >= fee else fee - bal)
 		return self._funds_available(bal >= fee, bal - fee if bal >= fee else fee - bal)
 
 
-	def final_inputs_ok_msg(self,funds_left):
+	def final_inputs_ok_msg(self, funds_left):
 		token_bal = (
 		token_bal = (
 			self.proto.coin_amt('0') if self.outputs[0].is_chg
 			self.proto.coin_amt('0') if self.outputs[0].is_chg
 			else self.inputs[0].amt - self.outputs[0].amt
 			else self.inputs[0].amt - self.outputs[0].amt

+ 11 - 11
mmgen/proto/eth/tx/online.py

@@ -12,24 +12,24 @@
 proto.eth.tx.online: Ethereum online signed transaction class
 proto.eth.tx.online: Ethereum online signed transaction class
 """
 """
 
 
-from ....util import msg,die
+from ....util import msg, die
 from ....color import orange
 from ....color import orange
 from ....tx import online as TxBase
 from ....tx import online as TxBase
 from .. import erigon_sleep
 from .. import erigon_sleep
-from .signed import Signed,TokenSigned
+from .signed import Signed, TokenSigned
 
 
-class OnlineSigned(Signed,TxBase.OnlineSigned):
+class OnlineSigned(Signed, TxBase.OnlineSigned):
 
 
-	async def send(self,prompt_user=True):
+	async def send(self, prompt_user=True):
 
 
 		self.check_correct_chain()
 		self.check_correct_chain()
 
 
 		if not self.disable_fee_check and (self.fee > self.proto.max_tx_fee):
 		if not self.disable_fee_check and (self.fee > self.proto.max_tx_fee):
-			die(2,'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
+			die(2, 'Transaction fee ({}) greater than {} max_tx_fee ({} {})!'.format(
 				self.fee,
 				self.fee,
 				self.proto.name,
 				self.proto.name,
 				self.proto.max_tx_fee,
 				self.proto.max_tx_fee,
-				self.proto.coin ))
+				self.proto.coin))
 
 
 		await self.status.display()
 		await self.status.display()
 
 
@@ -40,12 +40,12 @@ class OnlineSigned(Signed,TxBase.OnlineSigned):
 			m = 'BOGUS transaction NOT sent: {}'
 			m = 'BOGUS transaction NOT sent: {}'
 		else:
 		else:
 			try:
 			try:
-				ret = await self.rpc.call('eth_sendRawTransaction','0x'+self.serialized)
+				ret = await self.rpc.call('eth_sendRawTransaction', '0x'+self.serialized)
 			except Exception as e:
 			except Exception as e:
 				msg(orange('\n'+str(e)))
 				msg(orange('\n'+str(e)))
 				die(2, f'Send of MMGen transaction {self.txid} failed')
 				die(2, f'Send of MMGen transaction {self.txid} failed')
 			m = 'Transaction sent: {}'
 			m = 'Transaction sent: {}'
-			assert ret == '0x'+self.coin_txid,'txid mismatch (after sending)'
+			assert ret == '0x'+self.coin_txid, 'txid mismatch (after sending)'
 			await erigon_sleep(self)
 			await erigon_sleep(self)
 
 
 		msg(m.format(self.coin_txid.hl()))
 		msg(m.format(self.coin_txid.hl()))
@@ -58,7 +58,7 @@ class OnlineSigned(Signed,TxBase.OnlineSigned):
 		if 'token_addr' in self.txobj:
 		if 'token_addr' in self.txobj:
 			msg('Contract address: {}'.format(self.txobj['token_addr'].hl(0)))
 			msg('Contract address: {}'.format(self.txobj['token_addr'].hl(0)))
 
 
-class TokenOnlineSigned(TokenSigned,OnlineSigned):
+class TokenOnlineSigned(TokenSigned, OnlineSigned):
 
 
 	def parse_txfile_serialized_data(self):
 	def parse_txfile_serialized_data(self):
 		from ....addr import TokenAddr
 		from ....addr import TokenAddr
@@ -66,9 +66,9 @@ class TokenOnlineSigned(TokenSigned,OnlineSigned):
 		OnlineSigned.parse_txfile_serialized_data(self)
 		OnlineSigned.parse_txfile_serialized_data(self)
 		o = self.txobj
 		o = self.txobj
 		assert self.twctl.token == o['to']
 		assert self.twctl.token == o['to']
-		o['token_addr'] = TokenAddr(self.proto,o['to'])
+		o['token_addr'] = TokenAddr(self.proto, o['to'])
 		o['decimals']   = self.twctl.decimals
 		o['decimals']   = self.twctl.decimals
-		t = Token(self.cfg,self.proto,o['token_addr'],o['decimals'])
+		t = Token(self.cfg, self.proto, o['token_addr'], o['decimals'])
 		o['amt'] = t.transferdata2amt(o['data'])
 		o['amt'] = t.transferdata2amt(o['data'])
 		o['token_to'] = t.transferdata2sendaddr(o['data'])
 		o['token_to'] = t.transferdata2sendaddr(o['data'])
 
 

+ 10 - 10
mmgen/proto/eth/tx/signed.py

@@ -17,22 +17,22 @@ from ....obj import CoinTxID, ETHNonce, HexStr
 from ....addr import CoinAddr, TokenAddr
 from ....addr import CoinAddr, TokenAddr
 from .completed import Completed, TokenCompleted
 from .completed import Completed, TokenCompleted
 
 
-class Signed(Completed,TxBase.Signed):
+class Signed(Completed, TxBase.Signed):
 
 
 	desc = 'signed transaction'
 	desc = 'signed transaction'
 
 
 	def parse_txfile_serialized_data(self):
 	def parse_txfile_serialized_data(self):
 		from ..pyethereum.transactions import Transaction
 		from ..pyethereum.transactions import Transaction
 		from .. import rlp
 		from .. import rlp
-		etx = rlp.decode(bytes.fromhex(self.serialized),Transaction)
+		etx = rlp.decode(bytes.fromhex(self.serialized), Transaction)
 		d = etx.to_dict() # ==> hex values have '0x' prefix, 0 is '0x'
 		d = etx.to_dict() # ==> hex values have '0x' prefix, 0 is '0x'
-		for k in ('sender','to','data'):
+		for k in ('sender', 'to', 'data'):
 			if k in d:
 			if k in d:
-				d[k] = d[k].replace('0x','',1)
+				d[k] = d[k].replace('0x', '', 1)
 		o = {
 		o = {
-			'from':     CoinAddr(self.proto,d['sender']),
+			'from':     CoinAddr(self.proto, d['sender']),
 			# NB: for token, 'to' is token address
 			# NB: for token, 'to' is token address
-			'to':       CoinAddr(self.proto,d['to']) if d['to'] else None,
+			'to':       CoinAddr(self.proto, d['to']) if d['to'] else None,
 			'amt':      self.proto.coin_amt(d['value'], from_unit='wei'),
 			'amt':      self.proto.coin_amt(d['value'], from_unit='wei'),
 			'gasPrice': self.proto.coin_amt(d['gasprice'], from_unit='wei'),
 			'gasPrice': self.proto.coin_amt(d['gasprice'], from_unit='wei'),
 			'startGas': self.proto.coin_amt(d['startgas'], from_unit='wei'),
 			'startGas': self.proto.coin_amt(d['startgas'], from_unit='wei'),
@@ -40,15 +40,15 @@ class Signed(Completed,TxBase.Signed):
 			'data':     HexStr(d['data']) }
 			'data':     HexStr(d['data']) }
 		if o['data'] and not o['to']: # token- or contract-creating transaction
 		if o['data'] and not o['to']: # token- or contract-creating transaction
 			# NB: could be a non-token contract address:
 			# NB: could be a non-token contract address:
-			o['token_addr'] = TokenAddr(self.proto,etx.creates.hex())
+			o['token_addr'] = TokenAddr(self.proto, etx.creates.hex())
 			self.disable_fee_check = True
 			self.disable_fee_check = True
 		txid = CoinTxID(etx.hash.hex())
 		txid = CoinTxID(etx.hash.hex())
-		assert txid == self.coin_txid,"txid in tx.serialized doesn't match value in MMGen transaction file"
+		assert txid == self.coin_txid, "txid in tx.serialized doesn't match value in MMGen transaction file"
 		self.gas = o['startGas'] # approximate, but better than nothing
 		self.gas = o['startGas'] # approximate, but better than nothing
 		self.txobj = o
 		self.txobj = o
-		return d # 'token_addr','decimals' required by Token subclass
+		return d # 'token_addr', 'decimals' required by Token subclass
 
 
-class TokenSigned(TokenCompleted,Signed):
+class TokenSigned(TokenCompleted, Signed):
 	desc = 'signed transaction'
 	desc = 'signed transaction'
 
 
 	def parse_txfile_serialized_data(self):
 	def parse_txfile_serialized_data(self):

+ 11 - 11
mmgen/proto/eth/tx/status.py

@@ -13,38 +13,38 @@ proto.eth.tx.status: Ethereum transaction status class
 """
 """
 
 
 from ....tx import status as TxBase
 from ....tx import status as TxBase
-from ....util import msg,die,suf,capfirst
+from ....util import msg, die, suf, capfirst
 
 
 class Status(TxBase.Status):
 class Status(TxBase.Status):
 
 
-	async def display(self,usr_req=False):
+	async def display(self, usr_req=False):
 
 
 		tx = self.tx
 		tx = self.tx
 
 
 		async def is_in_mempool():
 		async def is_in_mempool():
 			if not 'full_node' in tx.rpc.caps:
 			if not 'full_node' in tx.rpc.caps:
 				return False
 				return False
-			if tx.rpc.daemon.id in ('parity','openethereum'):
+			if tx.rpc.daemon.id in ('parity', 'openethereum'):
 				pool = [x['hash'] for x in await tx.rpc.call('parity_pendingTransactions')]
 				pool = [x['hash'] for x in await tx.rpc.call('parity_pendingTransactions')]
-			elif tx.rpc.daemon.id in ('geth','erigon'):
+			elif tx.rpc.daemon.id in ('geth', 'erigon'):
 				res = await tx.rpc.call('txpool_content')
 				res = await tx.rpc.call('txpool_content')
 				pool = list(res['pending']) + list(res['queued'])
 				pool = list(res['pending']) + list(res['queued'])
 			return '0x'+tx.coin_txid in pool
 			return '0x'+tx.coin_txid in pool
 
 
 		async def is_in_wallet():
 		async def is_in_wallet():
-			d = await tx.rpc.call('eth_getTransactionReceipt','0x'+tx.coin_txid)
+			d = await tx.rpc.call('eth_getTransactionReceipt', '0x'+tx.coin_txid)
 			if d and 'blockNumber' in d and d['blockNumber'] is not None:
 			if d and 'blockNumber' in d and d['blockNumber'] is not None:
 				from collections import namedtuple
 				from collections import namedtuple
-				receipt_info = namedtuple('receipt_info',['confs','exec_status'])
+				receipt_info = namedtuple('receipt_info', ['confs', 'exec_status'])
 				return receipt_info(
 				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)
 				)
 				)
 
 
 		if await is_in_mempool():
 		if await is_in_mempool():
 			msg(
 			msg(
 				'Transaction is in mempool' if usr_req else
 				'Transaction is in mempool' if usr_req else
-				'Warning: transaction is in mempool!' )
+				'Warning: transaction is in mempool!')
 			return
 			return
 
 
 		if usr_req:
 		if usr_req:
@@ -56,8 +56,8 @@ class Status(TxBase.Status):
 						msg(f'{cd} failed to execute!')
 						msg(f'{cd} failed to execute!')
 					else:
 					else:
 						msg(f'{cd} successfully executed with status {ret.exec_status}')
 						msg(f'{cd} successfully executed with status {ret.exec_status}')
-				die(0,f'Transaction has {ret.confs} confirmation{suf(ret.confs)}')
-			die(1,'Transaction is neither in mempool nor blockchain!')
+				die(0, f'Transaction has {ret.confs} confirmation{suf(ret.confs)}')
+			die(1, 'Transaction is neither in mempool nor blockchain!')
 
 
 class TokenStatus(Status):
 class TokenStatus(Status):
 	pass
 	pass

+ 16 - 16
mmgen/proto/eth/tx/unsigned.py

@@ -21,26 +21,26 @@ from ....addr import CoinAddr, TokenAddr
 from ..contract import Token
 from ..contract import Token
 from .completed import Completed, TokenCompleted
 from .completed import Completed, TokenCompleted
 
 
-class Unsigned(Completed,TxBase.Unsigned):
+class Unsigned(Completed, TxBase.Unsigned):
 	desc = 'unsigned transaction'
 	desc = 'unsigned transaction'
 
 
 	def parse_txfile_serialized_data(self):
 	def parse_txfile_serialized_data(self):
 		d = json.loads(self.serialized)
 		d = json.loads(self.serialized)
 		o = {
 		o = {
-			'from':     CoinAddr(self.proto,d['from']),
+			'from':     CoinAddr(self.proto, d['from']),
 			# NB: for token, 'to' is sendto address
 			# NB: for token, 'to' is sendto address
-			'to':       CoinAddr(self.proto,d['to']) if d['to'] else None,
+			'to':       CoinAddr(self.proto, d['to']) if d['to'] else None,
 			'amt':      self.proto.coin_amt(d['amt']),
 			'amt':      self.proto.coin_amt(d['amt']),
 			'gasPrice': self.proto.coin_amt(d['gasPrice']),
 			'gasPrice': self.proto.coin_amt(d['gasPrice']),
 			'startGas': self.proto.coin_amt(d['startGas']),
 			'startGas': self.proto.coin_amt(d['startGas']),
 			'nonce':    ETHNonce(d['nonce']),
 			'nonce':    ETHNonce(d['nonce']),
 			'chainId':  None if d['chainId'] == 'None' else Int(d['chainId']),
 			'chainId':  None if d['chainId'] == 'None' else Int(d['chainId']),
-			'data':     HexStr(d['data']) }
+			'data':     HexStr(d['data'])}
 		self.gas = o['startGas'] # approximate, but better than nothing
 		self.gas = o['startGas'] # approximate, but better than nothing
 		self.txobj = o
 		self.txobj = o
-		return d # 'token_addr','decimals' required by Token subclass
+		return d # 'token_addr', 'decimals' required by Token subclass
 
 
-	async def do_sign(self,wif):
+	async def do_sign(self, wif):
 		o = self.txobj
 		o = self.txobj
 		o_conv = {
 		o_conv = {
 			'to':       bytes.fromhex(o['to'] or ''),
 			'to':       bytes.fromhex(o['to'] or ''),
@@ -61,11 +61,11 @@ class Unsigned(Completed,TxBase.Unsigned):
 
 
 		if o['data']:
 		if o['data']:
 			if o['to']:
 			if o['to']:
-				assert self.txobj['token_addr'] == TokenAddr(self.proto,etx.creates.hex()),'Token address mismatch'
+				assert self.txobj['token_addr'] == TokenAddr(self.proto, etx.creates.hex()), 'Token address mismatch'
 			else: # token- or contract-creating transaction
 			else: # token- or contract-creating transaction
-				self.txobj['token_addr'] = TokenAddr(self.proto,etx.creates.hex())
+				self.txobj['token_addr'] = TokenAddr(self.proto, etx.creates.hex())
 
 
-	async def sign(self,tx_num_str,keys): # return TX object or False; don't exit or raise exception
+	async def sign(self, tx_num_str, keys): # return TX object or False; don't exit or raise exception
 
 
 		from ....exception import TransactionChainMismatch
 		from ....exception import TransactionChainMismatch
 		try:
 		try:
@@ -84,28 +84,28 @@ class Unsigned(Completed,TxBase.Unsigned):
 			msg(f'{e}: transaction signing failed!')
 			msg(f'{e}: transaction signing failed!')
 			return False
 			return False
 
 
-class TokenUnsigned(TokenCompleted,Unsigned):
+class TokenUnsigned(TokenCompleted, Unsigned):
 	desc = 'unsigned transaction'
 	desc = 'unsigned transaction'
 
 
 	def parse_txfile_serialized_data(self):
 	def parse_txfile_serialized_data(self):
 		d = Unsigned.parse_txfile_serialized_data(self)
 		d = Unsigned.parse_txfile_serialized_data(self)
 		o = self.txobj
 		o = self.txobj
-		o['token_addr'] = TokenAddr(self.proto,d['token_addr'])
+		o['token_addr'] = TokenAddr(self.proto, d['token_addr'])
 		o['decimals'] = Int(d['decimals'])
 		o['decimals'] = Int(d['decimals'])
-		t = Token(self.cfg,self.proto,o['token_addr'],o['decimals'])
-		o['data'] = t.create_data(o['to'],o['amt'])
+		t = Token(self.cfg, self.proto, o['token_addr'], o['decimals'])
+		o['data'] = t.create_data(o['to'], o['amt'])
 		o['token_to'] = t.transferdata2sendaddr(o['data'])
 		o['token_to'] = t.transferdata2sendaddr(o['data'])
 
 
-	async def do_sign(self,wif):
+	async def do_sign(self, wif):
 		o = self.txobj
 		o = self.txobj
-		t = Token(self.cfg,self.proto,o['token_addr'],o['decimals'])
+		t = Token(self.cfg, self.proto, o['token_addr'], o['decimals'])
 		tx_in = t.make_tx_in(
 		tx_in = t.make_tx_in(
 				to_addr   = o['to'],
 				to_addr   = o['to'],
 				amt       = o['amt'],
 				amt       = o['amt'],
 				start_gas = self.start_gas,
 				start_gas = self.start_gas,
 				gasPrice  = o['gasPrice'],
 				gasPrice  = o['gasPrice'],
 				nonce     = o['nonce'])
 				nonce     = o['nonce'])
-		(self.serialized,self.coin_txid) = await t.txsign(tx_in,wif,o['from'],chain_id=o['chainId'])
+		(self.serialized, self.coin_txid) = await t.txsign(tx_in, wif, o['from'], chain_id=o['chainId'])
 
 
 class AutomountUnsigned(TxBase.AutomountUnsigned, Unsigned):
 class AutomountUnsigned(TxBase.AutomountUnsigned, Unsigned):
 	pass
 	pass