Browse Source

obj.py: move MMGenAddrType and other address-related data objects to addr.py

The MMGen Project 3 years ago
parent
commit
126a09d57d

+ 152 - 0
mmgen/addr.py

@@ -27,6 +27,158 @@ from .obj import *
 from .baseconv import *
 from .protocol import hash160
 from .key import PrivKey,PubKey
+from .seed import SeedID
+
+ati = namedtuple('addrtype_info',
+	['name','pubkey_type','compressed','gen_method','addr_fmt','wif_label','extra_attrs','desc'])
+
+class MMGenAddrType(str,Hilite,InitErrors,MMGenObject):
+	width = 1
+	trunc_ok = False
+	color = 'blue'
+
+	name        = ImmutableAttr(str)
+	pubkey_type = ImmutableAttr(str)
+	compressed  = ImmutableAttr(bool,set_none_ok=True)
+	gen_method  = ImmutableAttr(str,set_none_ok=True)
+	addr_fmt    = ImmutableAttr(str,set_none_ok=True)
+	wif_label   = ImmutableAttr(str,set_none_ok=True)
+	extra_attrs = ImmutableAttr(tuple,set_none_ok=True)
+	desc        = ImmutableAttr(str)
+
+	mmtypes = {
+		'L': ati('legacy',    'std', False,'p2pkh',   'p2pkh',   'wif', (), 'Legacy uncompressed address'),
+		'C': ati('compressed','std', True, 'p2pkh',   'p2pkh',   'wif', (), 'Compressed P2PKH address'),
+		'S': ati('segwit',    'std', True, 'segwit',  'p2sh',    'wif', (), 'Segwit P2SH-P2WPKH address'),
+		'B': ati('bech32',    'std', True, 'bech32',  'bech32',  'wif', (), 'Native Segwit (Bech32) address'),
+		'E': ati('ethereum',  'std', False,'ethereum','ethereum','privkey', ('wallet_passwd',),'Ethereum address'),
+		'Z': ati('zcash_z','zcash_z',False,'zcash_z', 'zcash_z', 'wif',     ('viewkey',),      'Zcash z-address'),
+		'M': ati('monero', 'monero', False,'monero',  'monero',  'spendkey',('viewkey','wallet_passwd'),'Monero address'),
+	}
+	def __new__(cls,proto,id_str,errmsg=None):
+		if isinstance(id_str,cls):
+			return id_str
+		try:
+			for k,v in cls.mmtypes.items():
+				if id_str in (k,v.name):
+					if id_str == v.name:
+						id_str = k
+					me = str.__new__(cls,id_str)
+					for k in v._fields:
+						setattr(me,k,getattr(v,k))
+					if me not in proto.mmtypes + ('P',):
+						raise ValueError(f'{me.name!r}: invalid address type for {proto.name} protocol')
+					me.proto = proto
+					return me
+			raise ValueError(f'{id_str}: unrecognized address type for protocol {proto.name}')
+		except Exception as e:
+			return cls.init_fail( e,
+				f"{errmsg or ''}{id_str!r}: invalid value for {cls.__name__} ({e!s})",
+				preformat = True )
+
+	@classmethod
+	def get_names(cls):
+		return [v.name for v in cls.mmtypes.values()]
+
+class MMGenPasswordType(MMGenAddrType):
+	mmtypes = {
+		'P': ati('password', 'password', None, None, None, None, None, 'Password generated from MMGen seed')
+	}
+
+class AddrIdx(MMGenIdx):
+	max_digits = 7
+
+def is_addr_idx(s):
+	return get_obj( AddrIdx, n=s, silent=True, return_bool=True )
+
+class AddrListID(str,Hilite,InitErrors,MMGenObject):
+	width = 10
+	trunc_ok = False
+	color = 'yellow'
+	def __new__(cls,sid,mmtype):
+		try:
+			assert type(sid) == SeedID, f'{sid!r} not a SeedID instance'
+			if not isinstance(mmtype,(MMGenAddrType,MMGenPasswordType)):
+				raise ValueError(f'{mmtype!r}: not an instance of MMGenAddrType or MMGenPasswordType')
+			me = str.__new__(cls,sid+':'+mmtype)
+			me.sid = sid
+			me.mmtype = mmtype
+			return me
+		except Exception as e:
+			return cls.init_fail(e, f'sid={sid}, mmtype={mmtype}')
+
+def is_addrlist_id(s):
+	return get_obj( AddrListID, sid=s, silent=True, return_bool=True )
+
+class MMGenID(str,Hilite,InitErrors,MMGenObject):
+	color = 'orange'
+	width = 0
+	trunc_ok = False
+	def __new__(cls,proto,id_str):
+		try:
+			ss = str(id_str).split(':')
+			assert len(ss) in (2,3),'not 2 or 3 colon-separated items'
+			t = proto.addr_type((ss[1],proto.dfl_mmtype)[len(ss)==2])
+			me = str.__new__(cls,'{}:{}:{}'.format(ss[0],t,ss[-1]))
+			me.sid = SeedID(sid=ss[0])
+			me.idx = AddrIdx(ss[-1])
+			me.mmtype = t
+			assert t in proto.mmtypes, f'{t}: invalid address type for {proto.cls_name}'
+			me.al_id = str.__new__(AddrListID,me.sid+':'+me.mmtype) # checks already done
+			me.sort_key = '{}:{}:{:0{w}}'.format(me.sid,me.mmtype,me.idx,w=me.idx.max_digits)
+			me.proto = proto
+			return me
+		except Exception as e:
+			return cls.init_fail(e,id_str)
+
+def is_mmgen_id(proto,s):
+	return get_obj( MMGenID, proto=proto, id_str=s, silent=True, return_bool=True )
+
+class CoinAddr(str,Hilite,InitErrors,MMGenObject):
+	color = 'cyan'
+	hex_width = 40
+	width = 1
+	trunc_ok = False
+	def __new__(cls,proto,addr):
+		if type(addr) == cls:
+			return addr
+		try:
+			assert set(addr) <= set(ascii_letters+digits),'contains non-alphanumeric characters'
+			me = str.__new__(cls,addr)
+			ap = proto.parse_addr(addr)
+			assert ap, f'coin address {addr!r} could not be parsed'
+			me.addr_fmt = ap.fmt
+			me.hex = ap.bytes.hex()
+			me.proto = proto
+			return me
+		except Exception as e:
+			return cls.init_fail(e,addr,objname=f'{proto.cls_name} address')
+
+	@classmethod
+	def fmtc(cls,addr,**kwargs):
+		w = kwargs['width'] or cls.width
+		return super().fmtc(addr[:w-2]+'..' if w < len(addr) else addr, **kwargs)
+
+def is_coin_addr(proto,s):
+	return get_obj( CoinAddr, proto=proto, addr=s, silent=True, return_bool=True )
+
+class TokenAddr(CoinAddr):
+	color = 'blue'
+
+class ViewKey(object):
+	def __new__(cls,proto,viewkey):
+		if proto.name == 'Zcash':
+			return ZcashViewKey.__new__(ZcashViewKey,proto,viewkey)
+		elif proto.name == 'Monero':
+			return MoneroViewKey.__new__(MoneroViewKey,viewkey)
+		else:
+			raise ValueError(f'{proto.name}: protocol does not support view keys')
+
+class MoneroViewKey(HexStr):
+	color,width,hexcase = 'cyan',64,'lower' # FIXME - no checking performed
+
+class ZcashViewKey(CoinAddr):
+	hex_width = 128
 
 class AddrGenerator(MMGenObject):
 	def __new__(cls,proto,addr_type):

+ 2 - 2
mmgen/addrdata.py

@@ -22,8 +22,8 @@ addrdata.py: MMGen AddrData and related classes
 
 from .util import vmsg,altcoin_subclass
 from .base_obj import AsyncInit
-from .obj import MMGenObject,MMGenDict,get_obj,AddrListID
-from .addr import MMGenID
+from .obj import MMGenObject,MMGenDict,get_obj
+from .addr import MMGenID,AddrListID
 from .addrlist import AddrListEntry,AddrListData,AddrList
 
 class AddrData(MMGenObject):

+ 2 - 1
mmgen/addrfile.py

@@ -31,9 +31,10 @@ from .util import (
 	keypress_confirm,
 )
 from .protocol import init_proto
-from .obj import *
+from .obj import MMGenObject,TwComment,WalletPassword,MMGenPWIDString
 from .seed import SeedID,is_seed_id
 from .key import PrivKey
+from .addr import ViewKey,AddrListID,MMGenPasswordType,is_addr_idx
 from .addrlist import KeyList,AddrListData,dmsg_sc
 from .passwdlist import PasswordList
 

+ 1 - 1
mmgen/addrlist.py

@@ -26,7 +26,7 @@ from .objmethods import MMGenObject,Hilite,InitErrors
 from .obj import MMGenListItem,ListItemAttr,MMGenDict,WalletPassword
 from .seed import SeedID
 from .key import PrivKey
-from .obj import MMGenID,MMGenAddrType,CoinAddr,AddrIdx,AddrListID,ViewKey
+from .addr import MMGenID,MMGenAddrType,CoinAddr,AddrIdx,AddrListID,ViewKey
 
 def dmsg_sc(desc,data):
 	from .globalvars import g

+ 3 - 3
mmgen/altcoins/eth/contract.py

@@ -23,11 +23,11 @@ altcoins.eth.contract: Ethereum contract and token classes for the MMGen suite
 from decimal import Decimal
 from . import rlp
 
+from mmgen.util import msg,pp_msg
 from mmgen.globalvars import g
-from mmgen.common import *
 from mmgen.base_obj import AsyncInit
-from mmgen.obj import MMGenObject,CoinAddr,TokenAddr,CoinTxID
-from mmgen.util import msg
+from mmgen.obj import MMGenObject,CoinTxID
+from mmgen.addr import CoinAddr,TokenAddr
 from .obj import ETHAmt
 
 def parse_abi(s):

+ 8 - 5
mmgen/altcoins/eth/tw.py

@@ -20,9 +20,12 @@
 altcoins.eth.tw: Ethereum tracking wallet and related classes for the MMGen suite
 """
 
-from mmgen.common import *
-from mmgen.obj import TwLabel,is_coin_addr,is_mmgen_id,ListItemAttr,ImmutableAttr
-from mmgen.tw import TrackingWallet,TwAddrList,TwUnspentOutputs,TwGetBalance
+import os
+
+from mmgen.util import msg,vmsg,ymsg,write_mode
+from mmgen.obj import ListItemAttr,ImmutableAttr
+from mmgen.tw import TrackingWallet,TwAddrList,TwUnspentOutputs,TwGetBalance,TwLabel
+from mmgen.addr import is_coin_addr,is_mmgen_id
 from mmgen.addrdata import AddrData,TwAddrData
 from .contract import Token,TokenResolve
 from .obj import ETHAmt
@@ -169,7 +172,7 @@ class EthereumTokenTrackingWallet(EthereumTrackingWallet):
 				from mmgen.exception import UnrecognizedTokenSymbol
 				raise UnrecognizedTokenSymbol(f'Specified token {proto.tokensym!r} could not be resolved!')
 
-		from mmgen.obj import TokenAddr
+		from mmgen.addr import TokenAddr
 		self.token = TokenAddr(proto,token_addr)
 
 		if self.token not in self.data['tokens']:
@@ -300,7 +303,7 @@ class EthereumTwAddrList(TwAddrList):
 		tw_dict = self.wallet.mmid_ordered_dict
 		self.total = self.proto.coin_amt('0')
 
-		from mmgen.obj import CoinAddr
+		from mmgen.addr import CoinAddr
 		for mmid,d in list(tw_dict.items()):
 #			if d['confirmations'] < minconf: continue # cannot get confirmations for eth account
 			label = TwLabel(self.proto,mmid+' '+d['comment'])

+ 10 - 2
mmgen/altcoins/eth/tx.py

@@ -21,9 +21,17 @@ altcoins.eth.tx: Ethereum transaction classes for the MMGen suite
 """
 
 import json
-from mmgen.common import *
+from collections import namedtuple
+
+from decimal import Decimal
+
+from mmgen.globalvars import g
+from mmgen.color import red,yellow,blue,pink
+from mmgen.opts import opt
+from mmgen.util import msg,msg_r,ymsg,dmsg,fmt,line_input,is_int,is_hex_str,make_chksum_6,die,suf,capfirst,pp_fmt
 from mmgen.exception import TransactionChainMismatch
-from mmgen.obj import *
+from mmgen.obj import Int,Str,HexStr,CoinTxID,MMGenTxID
+from mmgen.addr import MMGenID,CoinAddr,TokenAddr,is_mmgen_id,is_coin_addr
 
 from mmgen.tx import MMGenTX
 from mmgen.tw import TrackingWallet

+ 1 - 1
mmgen/main_split.py

@@ -101,7 +101,7 @@ if opt.other_coin.lower() not in [e[2] for e in proto.forks if e[3] == True]:
 if len(cmd_args) != 2:
 	die(1,f'This command requires exactly two {g.proj_name} addresses as arguments')
 
-from .obj import MMGenID
+from .addr import MMGenID
 try:
 	mmids = [MMGenID(a) for a in cmd_args]
 except:

+ 1 - 153
mmgen/obj.py

@@ -57,18 +57,6 @@ def get_obj(objname,*args,**kwargs):
 	else:
 		return True if return_bool else ret
 
-def is_addr_idx(s):
-	return get_obj(AddrIdx, n=s, silent=True, return_bool=True)
-
-def is_addrlist_id(s):
-	return get_obj(AddrListID, sid=s, silent=True, return_bool=True)
-
-def is_mmgen_id(proto,s):
-	return get_obj(MMGenID, proto=proto, id_str=s, silent=True, return_bool=True)
-
-def is_coin_addr(proto,s):
-	return get_obj(CoinAddr, proto=proto, addr=s, silent=True, return_bool=True)
-
 # dict that keeps a list of keys for efficient lookup by index
 class IndexedDict(dict):
 
@@ -268,9 +256,6 @@ class MMGenListItem(MMGenObject):
 class MMGenIdx(Int):
 	min_val = 1
 
-class AddrIdx(MMGenIdx):
-	max_digits = 7
-
 class MMGenRange(tuple,InitErrors,MMGenObject):
 
 	min_idx = None
@@ -314,67 +299,6 @@ class MMGenRange(tuple,InitErrors,MMGenObject):
 	def items(self):
 		return list(self.iterate())
 
-class CoinAddr(str,Hilite,InitErrors,MMGenObject):
-	color = 'cyan'
-	hex_width = 40
-	width = 1
-	trunc_ok = False
-	def __new__(cls,proto,addr):
-		if type(addr) == cls:
-			return addr
-		try:
-			assert set(addr) <= set(ascii_letters+digits),'contains non-alphanumeric characters'
-			me = str.__new__(cls,addr)
-			ap = proto.parse_addr(addr)
-			assert ap, f'coin address {addr!r} could not be parsed'
-			me.addr_fmt = ap.fmt
-			me.hex = ap.bytes.hex()
-			me.proto = proto
-			return me
-		except Exception as e:
-			return cls.init_fail(e,addr,objname=f'{proto.cls_name} address')
-
-	@classmethod
-	def fmtc(cls,addr,**kwargs):
-		w = kwargs['width'] or cls.width
-		return super().fmtc(addr[:w-2]+'..' if w < len(addr) else addr, **kwargs)
-
-class TokenAddr(CoinAddr):
-	color = 'blue'
-
-class ViewKey(object):
-	def __new__(cls,proto,viewkey):
-		if proto.name == 'Zcash':
-			return ZcashViewKey.__new__(ZcashViewKey,proto,viewkey)
-		elif proto.name == 'Monero':
-			return MoneroViewKey.__new__(MoneroViewKey,viewkey)
-		else:
-			raise ValueError(f'{proto.name}: protocol does not support view keys')
-
-class ZcashViewKey(CoinAddr): hex_width = 128
-
-class MMGenID(str,Hilite,InitErrors,MMGenObject):
-	color = 'orange'
-	width = 0
-	trunc_ok = False
-	def __new__(cls,proto,id_str):
-		from .seed import SeedID
-		try:
-			ss = str(id_str).split(':')
-			assert len(ss) in (2,3),'not 2 or 3 colon-separated items'
-			t = proto.addr_type((ss[1],proto.dfl_mmtype)[len(ss)==2])
-			me = str.__new__(cls,'{}:{}:{}'.format(ss[0],t,ss[-1]))
-			me.sid = SeedID(sid=ss[0])
-			me.idx = AddrIdx(ss[-1])
-			me.mmtype = t
-			assert t in proto.mmtypes, f'{t}: invalid address type for {proto.cls_name}'
-			me.al_id = str.__new__(AddrListID,me.sid+':'+me.mmtype) # checks already done
-			me.sort_key = '{}:{}:{:0{w}}'.format(me.sid,me.mmtype,me.idx,w=me.idx.max_digits)
-			me.proto = proto
-			return me
-		except Exception as e:
-			return cls.init_fail(e,id_str)
-
 class TwMMGenID(str,Hilite,InitErrors,MMGenObject):
 	color = 'orange'
 	width = 0
@@ -383,6 +307,7 @@ class TwMMGenID(str,Hilite,InitErrors,MMGenObject):
 		if type(id_str) == cls:
 			return id_str
 		ret = None
+		from .addr import MMGenID
 		try:
 			ret = MMGenID(proto,id_str)
 			sort_key,idtype = ret.sort_key,'mmgen'
@@ -449,29 +374,9 @@ class CoinTxID(HexStr):
 class WalletPassword(HexStr):
 	color,width,hexcase = ('blue',32,'lower')
 
-class MoneroViewKey(HexStr):
-	color,width,hexcase = ('cyan',64,'lower') # FIXME - no checking performed
-
 class MMGenTxID(HexStr):
 	color,width,hexcase = ('red',6,'upper')
 
-class AddrListID(str,Hilite,InitErrors,MMGenObject):
-	width = 10
-	trunc_ok = False
-	color = 'yellow'
-	def __new__(cls,sid,mmtype):
-		from .seed import SeedID
-		try:
-			assert type(sid) == SeedID, f'{sid!r} not a SeedID instance'
-			if not isinstance(mmtype,(MMGenAddrType,MMGenPasswordType)):
-				raise ValueError(f'{mmtype!r}: not an instance of MMGenAddrType or MMGenPasswordType')
-			me = str.__new__(cls,sid+':'+mmtype)
-			me.sid = sid
-			me.mmtype = mmtype
-			return me
-		except Exception as e:
-			return cls.init_fail(e, f'sid={sid}, mmtype={mmtype}')
-
 class MMGenLabel(str,Hilite,InitErrors):
 	color = 'pink'
 	allowed = []
@@ -535,60 +440,3 @@ class MMGenPWIDString(MMGenLabel):
 	desc = 'password ID string'
 	forbidden = list(' :/\\')
 	trunc_ok = False
-
-from collections import namedtuple
-ati = namedtuple('addrtype_info',
-	['name','pubkey_type','compressed','gen_method','addr_fmt','wif_label','extra_attrs','desc'])
-
-class MMGenAddrType(str,Hilite,InitErrors,MMGenObject):
-	width = 1
-	trunc_ok = False
-	color = 'blue'
-
-	name        = ImmutableAttr(str)
-	pubkey_type = ImmutableAttr(str)
-	compressed  = ImmutableAttr(bool,set_none_ok=True)
-	gen_method  = ImmutableAttr(str,set_none_ok=True)
-	addr_fmt    = ImmutableAttr(str,set_none_ok=True)
-	wif_label   = ImmutableAttr(str,set_none_ok=True)
-	extra_attrs = ImmutableAttr(tuple,set_none_ok=True)
-	desc        = ImmutableAttr(str)
-
-	mmtypes = {
-		'L': ati('legacy',    'std', False,'p2pkh',   'p2pkh',   'wif', (), 'Legacy uncompressed address'),
-		'C': ati('compressed','std', True, 'p2pkh',   'p2pkh',   'wif', (), 'Compressed P2PKH address'),
-		'S': ati('segwit',    'std', True, 'segwit',  'p2sh',    'wif', (), 'Segwit P2SH-P2WPKH address'),
-		'B': ati('bech32',    'std', True, 'bech32',  'bech32',  'wif', (), 'Native Segwit (Bech32) address'),
-		'E': ati('ethereum',  'std', False,'ethereum','ethereum','privkey', ('wallet_passwd',),'Ethereum address'),
-		'Z': ati('zcash_z','zcash_z',False,'zcash_z', 'zcash_z', 'wif',     ('viewkey',),      'Zcash z-address'),
-		'M': ati('monero', 'monero', False,'monero',  'monero',  'spendkey',('viewkey','wallet_passwd'),'Monero address'),
-	}
-	def __new__(cls,proto,id_str,errmsg=None):
-		if isinstance(id_str,cls):
-			return id_str
-		try:
-			for k,v in cls.mmtypes.items():
-				if id_str in (k,v.name):
-					if id_str == v.name:
-						id_str = k
-					me = str.__new__(cls,id_str)
-					for k in v._fields:
-						setattr(me,k,getattr(v,k))
-					if me not in proto.mmtypes + ('P',):
-						raise ValueError(f'{me.name!r}: invalid address type for {proto.name} protocol')
-					me.proto = proto
-					return me
-			raise ValueError(f'{id_str}: unrecognized address type for protocol {proto.name}')
-		except Exception as e:
-			return cls.init_fail( e,
-				f"{errmsg or ''}{id_str!r}: invalid value for {cls.__name__} ({e!s})",
-				preformat = True )
-
-	@classmethod
-	def get_names(cls):
-		return [v.name for v in cls.mmtypes.values()]
-
-class MMGenPasswordType(MMGenAddrType):
-	mmtypes = {
-		'P': ati('password', 'password', None, None, None, None, None, 'Password generated from MMGen seed')
-	}

+ 0 - 1
mmgen/protocol.py

@@ -25,7 +25,6 @@ from collections import namedtuple
 
 from .util import msg,ymsg,Msg,ydie
 from .devtools import *
-from .obj import CoinAddr,MMGenAddrType
 from .globalvars import g
 from .amt import BTCAmt,LTCAmt,BCHAmt,XMRAmt
 from .altcoins.eth.obj import ETHAmt

+ 1 - 1
mmgen/tool.py

@@ -230,7 +230,7 @@ def _process_result(ret,pager=False,print_result=False):
 	else:
 		ydie(1,f'tool.py: can’t handle return value of type {type(ret).__name__!r}')
 
-from .obj import MMGenAddrType
+from .addr import MMGenAddrType
 
 def conv_cls_bip39():
 	from .bip39 import bip39

+ 6 - 5
mmgen/tw.py

@@ -47,8 +47,8 @@ from .util import (
 )
 from .base_obj import AsyncInit
 from .objmethods import Hilite,InitErrors,MMGenObject
-from .obj import *
-from .tx import is_mmgen_id,is_coin_addr
+from .obj import ImmutableAttr,ListItemAttr,MMGenListItem,MMGenList,MMGenDict,TwComment,get_obj,TwLabel,TwMMGenID
+from .addr import CoinAddr,MMGenID,AddrIdx,is_mmgen_id,is_coin_addr
 from .rpc import rpc_init
 
 def get_tw_label(proto,s):
@@ -59,7 +59,8 @@ def get_tw_label(proto,s):
 		return TwLabel(proto,s)
 	except BadTwComment:
 		raise
-	except:
+	except Exception as e:
+		print(e)
 		return None
 
 class TwUnspentOutputs(MMGenObject,metaclass=AsyncInit):
@@ -98,8 +99,8 @@ Actions: [q]uit view, [p]rint to file, pager [v]iew, [w]ide view, add [l]abel:
 		amt          = ImmutableAttr(None)
 		amt2         = ListItemAttr(None)
 		label        = ListItemAttr('TwComment',reassign_ok=True)
-		twmmid       = ImmutableAttr('TwMMGenID',include_proto=True)
-		addr         = ImmutableAttr('CoinAddr',include_proto=True)
+		twmmid       = ImmutableAttr(TwMMGenID,include_proto=True)
+		addr         = ImmutableAttr(CoinAddr,include_proto=True)
 		confs        = ImmutableAttr(int,typeconv=False)
 		date         = ListItemAttr(int,typeconv=False,reassign_ok=True)
 		scriptPubKey = ImmutableAttr('HexStr')

+ 3 - 2
mmgen/tx.py

@@ -24,6 +24,7 @@ import sys,os,json
 from stat import *
 from .common import *
 from .obj import *
+from .addr import MMGenID,CoinAddr,is_mmgen_id,is_coin_addr
 
 wmsg = lambda k: {
 	'addr_in_addrfile_only': """
@@ -210,8 +211,8 @@ class MMGenTxIO(MMGenListItem):
 	vout     = ListItemAttr(int,typeconv=False)
 	amt      = ImmutableAttr(None)
 	label    = ListItemAttr('TwComment',reassign_ok=True)
-	mmid     = ListItemAttr('MMGenID',include_proto=True)
-	addr     = ImmutableAttr('CoinAddr',include_proto=True)
+	mmid     = ListItemAttr(MMGenID,include_proto=True)
+	addr     = ImmutableAttr(CoinAddr,include_proto=True)
 	confs    = ListItemAttr(int) # confs of type long exist in the wild, so convert
 	txid     = ListItemAttr('CoinTxID')
 	have_wif = ListItemAttr(bool,typeconv=False,delete_ok=True)

+ 2 - 1
mmgen/txsign.py

@@ -21,8 +21,9 @@ txsign: Sign a transaction generated by 'mmgen-txcreate'
 """
 
 from .common import *
+from .obj import MMGenList
+from .addr import MMGenAddrType
 from .addrlist import AddrIdxList,KeyAddrList
-from .obj import MMGenAddrType,MMGenList
 from .wallet import Wallet,WalletUnenc,WalletEnc,MMGenWallet
 from .tx import MMGenTX
 

+ 4 - 3
mmgen/xmrwallet.py

@@ -24,12 +24,13 @@ import os,re,time,json
 from collections import namedtuple
 from .common import *
 from .objmethods import Hilite,InitErrors
-from .rpc import MoneroRPCClientRaw,MoneroWalletRPCClient,json_encoder
+from .obj import CoinTxID
 from .seed import SeedID
-from .daemon import MoneroWalletDaemon
 from .protocol import _b58a,init_proto
+from .addr import CoinAddr,AddrIdx
 from .addrlist import KeyAddrList,AddrIdxList
-from .obj import CoinAddr,CoinTxID,AddrIdx
+from .rpc import MoneroRPCClientRaw,MoneroWalletRPCClient,json_encoder
+from .daemon import MoneroWalletDaemon
 
 xmrwallet_uarg_info = (
 	lambda e,hp: {

+ 1 - 2
test/gentest.py

@@ -401,9 +401,8 @@ def parse_arg2():
 # begin execution
 from mmgen.protocol import init_proto
 from mmgen.altcoin import CoinInfo as ci
-from mmgen.obj import MMGenAddrType
 from mmgen.key import PrivKey
-from mmgen.addr import KeyGenerator,AddrGenerator
+from mmgen.addr import KeyGenerator,AddrGenerator,MMGenAddrType
 
 addr_type = MMGenAddrType(
 	proto = proto,

+ 1 - 1
test/tooltest.py

@@ -186,7 +186,7 @@ if opt.list_names:
 	die(0,'\n{}\n  {}'.format(yellow('Untested commands:'),'\n  '.join(uc)))
 
 from mmgen.key import is_wif
-from mmgen.tx import is_coin_addr
+from mmgen.addr import is_coin_addr
 def is_wif_loc(s):
 	return is_wif(proto,s)
 def is_coin_addr_loc(s):

+ 1 - 1
test/tooltest2.py

@@ -44,7 +44,7 @@ def is_str(s):
 	return type(s) == str
 
 from mmgen.key import is_wif
-from mmgen.obj import is_coin_addr
+from mmgen.addr import is_coin_addr
 def is_wif_loc(s):
 	return is_wif(proto,s)
 def is_coin_addr_loc(s):