Support 40-character UTF-8 tracking wallet comments
This commit is contained in:
parent
896c7fe996
commit
d49c8627aa
6 changed files with 31 additions and 33 deletions
|
|
@ -494,7 +494,7 @@ class TwMMGenID(str,Hilite,InitErrors,MMGenObject):
|
|||
return me
|
||||
|
||||
# contains TwMMGenID,TwComment. Not for display
|
||||
class TwLabel(str,InitErrors,MMGenObject):
|
||||
class TwLabel(unicode,InitErrors,MMGenObject):
|
||||
def __new__(cls,s,on_fail='die'):
|
||||
if type(s) == cls: return s
|
||||
cls.arg_chk(cls,on_fail)
|
||||
|
|
@ -502,7 +502,7 @@ class TwLabel(str,InitErrors,MMGenObject):
|
|||
ss = s.split(None,1)
|
||||
mmid = TwMMGenID(ss[0],on_fail='raise')
|
||||
comment = TwComment(ss[1] if len(ss) == 2 else '',on_fail='raise')
|
||||
me = str.__new__(cls,'{}{}'.format(mmid,' {}'.format(comment) if comment else ''))
|
||||
me = unicode.__new__(cls,u'{}{}'.format(mmid,u' {}'.format(comment) if comment else ''))
|
||||
me.mmid = mmid
|
||||
me.comment = comment
|
||||
return me
|
||||
|
|
@ -671,8 +671,7 @@ class MMGenWalletLabel(MMGenLabel):
|
|||
desc = 'wallet label'
|
||||
|
||||
class TwComment(MMGenLabel):
|
||||
max_len = 32
|
||||
allowed = map(unichr,range(32,127))
|
||||
max_len = 40
|
||||
desc = 'tracking wallet comment'
|
||||
|
||||
class MMGenTXLabel(MMGenLabel):
|
||||
|
|
|
|||
15
mmgen/rpc.py
15
mmgen/rpc.py
|
|
@ -103,20 +103,16 @@ class CoinDaemonRPCConnection(object):
|
|||
|
||||
dmsg_rpc('=== request() debug ===')
|
||||
dmsg_rpc(' RPC POST data ==> {}\n'.format(p))
|
||||
caller = self
|
||||
|
||||
class MyJSONEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj,g.proto.coin_amt):
|
||||
return g.proto.get_rpc_coin_amt_type()(obj)
|
||||
return json.JSONEncoder.default(self, obj)
|
||||
|
||||
# TODO: UTF-8 labels
|
||||
# if type(p) != list and p['method'] == 'importaddress':
|
||||
# dump = json.dumps(p,cls=MyJSONEncoder,ensure_ascii=False)
|
||||
# print(dump)
|
||||
|
||||
dmsg_rpc(' RPC AUTHORIZATION data ==> raw: [{}]\n{}enc: [Basic {}]\n'.format(
|
||||
self.auth_str,' '*31,base64.b64encode(self.auth_str)))
|
||||
|
||||
try:
|
||||
hc.request('POST', '/', json.dumps(p,cls=MyJSONEncoder), {
|
||||
'Host': self.host,
|
||||
|
|
@ -146,15 +142,14 @@ class CoinDaemonRPCConnection(object):
|
|||
e2 = str(e1)
|
||||
return do_fail(r,1,e2)
|
||||
|
||||
r2 = r.read()
|
||||
r2 = r.read().decode('utf8')
|
||||
|
||||
dmsg_rpc(' RPC REPLY data ==> {}\n'.format(r2))
|
||||
dmsg_rpc(u' RPC REPLY data ==> {}\n'.format(r2))
|
||||
|
||||
if not r2:
|
||||
return do_fail(r,2,'Error: empty reply')
|
||||
|
||||
# from decimal import Decimal
|
||||
r3 = json.loads(r2.decode('utf8'), parse_float=Decimal)
|
||||
r3 = json.loads(r2,parse_float=Decimal)
|
||||
ret = []
|
||||
|
||||
for resp in r3 if cf['batch'] else [r3]:
|
||||
|
|
|
|||
|
|
@ -725,7 +725,7 @@ def Listaddresses(addrs='',minconf=1,
|
|||
|
||||
out = ([],[green('Chain: {}'.format(g.chain.upper()))])[g.chain in ('testnet','regtest')]
|
||||
|
||||
fs = '{{mid}}{} {{cmt}} {{amt}}{}'.format(('',' {addr}')[showbtcaddrs],('',' {age}')[show_age])
|
||||
fs = u'{{mid}}{} {{cmt}} {{amt}}{}'.format(('',' {addr}')[showbtcaddrs],('',' {age}')[show_age])
|
||||
mmaddrs = [k for k in addrs.keys() if k.type == 'mmgen']
|
||||
max_mmid_len = max(len(k) for k in mmaddrs) + 2 if mmaddrs else 10
|
||||
max_cmt_len = max(max(len(v['lbl'].comment) for v in addrs.values()),7)
|
||||
|
|
@ -835,6 +835,6 @@ def Twview(pager=False,reverse=False,wide=False,minconf=1,sort='age',show_days=T
|
|||
def Add_label(mmaddr_or_coin_addr,label):
|
||||
rpc_init()
|
||||
from mmgen.tw import MMGenTrackingWallet
|
||||
MMGenTrackingWallet.add_label(mmaddr_or_coin_addr,label) # dies on failure
|
||||
MMGenTrackingWallet.add_label(mmaddr_or_coin_addr,label,on_fail='raise')
|
||||
|
||||
def Remove_label(mmaddr_or_coin_addr): Add_label(mmaddr_or_coin_addr,'')
|
||||
|
|
|
|||
20
mmgen/tw.py
20
mmgen/tw.py
|
|
@ -162,7 +162,7 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
|
|||
out = [hdr_fmt.format(' '.join(self.sort_info()),g.coin,self.total.hl())]
|
||||
if g.chain in ('testnet','regtest'):
|
||||
out += [green('Chain: {}'.format(g.chain.upper()))]
|
||||
fs = ' {:%s} {:%s} {:2} {} {} {:<}' % (col1_w,tx_w)
|
||||
fs = u' {:%s} {:%s} {:2} {} {} {:<}' % (col1_w,tx_w)
|
||||
out += [fs.format('Num',
|
||||
'TXid'.ljust(tx_w - 5) + ' Vout', '',
|
||||
'Address'.ljust(addr_w),
|
||||
|
|
@ -175,10 +175,10 @@ watch-only wallet using '{}-addrimport' and then re-run this program.
|
|||
else i.twmmid if i.twmmid.type=='mmgen'
|
||||
else 'Non-{}'.format(g.proj_name),width=mmid_w,color=True)
|
||||
if self.show_mmid:
|
||||
addr_out = '{} {}'.format(
|
||||
addr_out = u'{} {}'.format(
|
||||
type(i.addr).fmtc(addr_dots,width=btaddr_w,color=True) if i.skip == 'addr' \
|
||||
else i.addr.fmt(width=btaddr_w,color=True),
|
||||
'{} {}'.format(mmid_disp,i.label.fmt(width=label_w,color=True) \
|
||||
u'{} {}'.format(mmid_disp,i.label.fmt(width=label_w,color=True) \
|
||||
if label_w > 0 else ''))
|
||||
else:
|
||||
addr_out = type(i.addr).fmtc(addr_dots,width=addr_w,color=True) \
|
||||
|
|
@ -280,10 +280,10 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
|
|||
idx,lbl = self.get_idx_and_label_from_user()
|
||||
if idx:
|
||||
e = self.unspent[idx-1]
|
||||
if type(self).add_label(e.twmmid,lbl,addr=e.addr):
|
||||
if type(self).add_label(e.twmmid,lbl.decode('utf8'),addr=e.addr):
|
||||
self.get_unspent_data()
|
||||
self.do_sort()
|
||||
msg('{}\n{}\n{}'.format(self.fmt_display,prompt,p))
|
||||
msg(u'{}\n{}\n{}'.format(self.fmt_display,prompt,p))
|
||||
else:
|
||||
msg('Label could not be added\n{}\n{}'.format(prompt,p))
|
||||
elif reply == 'M': self.do_sort('twmmid'); self.show_mmid = True
|
||||
|
|
@ -314,7 +314,7 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
|
|||
|
||||
# returns on failure
|
||||
@classmethod
|
||||
def add_label(cls,arg1,label='',addr=None,silent=False):
|
||||
def add_label(cls,arg1,label='',addr=None,silent=False,on_fail='return'):
|
||||
from mmgen.tx import is_mmgen_id,is_coin_addr
|
||||
mmaddr,coinaddr = None,None
|
||||
if is_coin_addr(addr or arg1):
|
||||
|
|
@ -345,10 +345,10 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
|
|||
|
||||
mmaddr = TwMMGenID(mmaddr)
|
||||
|
||||
cmt = TwComment(label,on_fail='return')
|
||||
cmt = TwComment(label,on_fail=on_fail)
|
||||
if cmt in (False,None): return False
|
||||
|
||||
lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)]) # label is ASCII for now
|
||||
lbl = TwLabel(mmaddr + ('',' '+cmt)[bool(cmt)],on_fail=on_fail)
|
||||
|
||||
# NOTE: this works because importaddress() removes the old account before
|
||||
# associating the new account with the address.
|
||||
|
|
@ -366,8 +366,8 @@ Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
|
|||
m = mmaddr.type.replace('mmg','MMG')
|
||||
a = mmaddr.replace(g.proto.base_coin.lower()+':','')
|
||||
s = '{} address {} in tracking wallet'.format(m,a)
|
||||
if label: msg("Added label '{}' to {}".format(label,s))
|
||||
else: msg('Removed label from {}'.format(s))
|
||||
if label: msg(u"Added label '{}' to {}".format(label,s))
|
||||
else: msg(u'Removed label from {}'.format(s))
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
|
|
|
|||
|
|
@ -949,7 +949,7 @@ class MMGenTX(MMGenObject):
|
|||
('','confirmations:','{} (around {} days)'.format(confs,days) if blockcount!=None else '')
|
||||
] if ip else icommon + [
|
||||
('','change:',green('True') if e.is_chg else '')]
|
||||
io_out += '\n'.join([('{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
|
||||
io_out += '\n'.join([(u'{:>3} {:<8} {}'.format(*d)) for d in items if d[2]]) + '\n\n'
|
||||
return io_out
|
||||
|
||||
hdr_fs = (
|
||||
|
|
|
|||
16
test/test.py
16
test/test.py
|
|
@ -2713,9 +2713,9 @@ class MMGenTestSuite(object):
|
|||
sid = self.regtest_user_sid('alice')
|
||||
return self.regtest_user_remove_label(name,'alice',sid+':C:1')
|
||||
|
||||
def regtest_user_chk_label(self,name,user,addr,label):
|
||||
def regtest_user_chk_label(self,name,user,addr,label,label_pat=None):
|
||||
t = MMGenExpect(name,'mmgen-tool',['--'+user,'listaddresses','all_labels=1'])
|
||||
t.expect('{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,label),regex=True)
|
||||
t.expect(ur'{}\s+\S{{30}}\S+\s+{}\s+'.format(addr,label_pat or label),regex=True)
|
||||
t.ok()
|
||||
|
||||
def regtest_alice_chk_label1(self,name):
|
||||
|
|
@ -2726,9 +2726,16 @@ class MMGenTestSuite(object):
|
|||
sid = self.regtest_user_sid('alice')
|
||||
return self.regtest_user_chk_label(name,'alice',sid+':C:1','Replacement Label')
|
||||
|
||||
utf8_label = u'Edited label (40 characters, UTF8) α-β-γ'
|
||||
utf8_label_pat = ur'Edited label \(40 characters, UTF8\) ..-..-..'
|
||||
|
||||
def regtest_alice_edit_label1(self,name):
|
||||
return self.regtest_user_edit_label(name,'alice','1',self.utf8_label)
|
||||
|
||||
def regtest_alice_chk_label3(self,name):
|
||||
sid = self.regtest_user_sid('alice')
|
||||
return self.regtest_user_chk_label(name,'alice',sid+':C:1','Edited Label')
|
||||
return self.regtest_user_chk_label(name,'alice',sid+':C:1',self.utf8_label,
|
||||
label_pat=self.utf8_label_pat)
|
||||
|
||||
def regtest_alice_chk_label4(self,name):
|
||||
sid = self.regtest_user_sid('alice')
|
||||
|
|
@ -2743,9 +2750,6 @@ class MMGenTestSuite(object):
|
|||
t.expect(r"'q'=quit view, .*?:.",'q',regex=True)
|
||||
t.ok()
|
||||
|
||||
def regtest_alice_edit_label1(self,name):
|
||||
return self.regtest_user_edit_label(name,'alice','1','Edited Label')
|
||||
|
||||
def regtest_stop(self,name):
|
||||
t = MMGenExpect(name,'mmgen-regtest',['stop'])
|
||||
t.ok()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue