Skip to content

Commit

Permalink
txcreate,twview,listaddresses: display transaction date
Browse files Browse the repository at this point in the history
- The `mmgen-tool` `listaddresses` and `twview` commands, as well as the
  unspent outputs menu of `mmgen-txcreate`, can now display the date/time of
  each output in addition to its number of confirmations, block, or age in
  days.  Two date display precisions are available: “approx”, an estimate based
  on the historical average block confirmation interval, and “exact”, the
  timestamp of the block containing the output.  Since display of the exact
  date requires an extra RPC call per output, precision defaults to “approx”.
  The setting also affects the precision of the age-in-days output.

Usage:

    $ mmgen-txcreate -i # 'D' to cycle through display opts, 'x' for exact age
    $ mmgen-tool listaddresses age_fmt=date exact_age=1 # (or age_fmt=date_time)
    $ mmgen-tool twview age_fmt=date exact_age=1        # (or age_fmt=date_time)

Testing:

    $ test/test.py -ne regtest
    $ test/test.py -ne --coin=eth ethdev
  • Loading branch information
mmgen committed Apr 4, 2020
1 parent de7fba0 commit b671453
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 67 deletions.
6 changes: 4 additions & 2 deletions mmgen/altcoins/eth/tw.py
Expand Up @@ -304,9 +304,11 @@ class MMGenTwUnspentOutput(MMGenListItem):
twmmid = MMGenImmutableAttr('twmmid','TwMMGenID')
addr = MMGenImmutableAttr('addr','CoinAddr')
confs = MMGenImmutableAttr('confs',int,typeconv=False)
days = MMGenListItemAttr('days',int,typeconv=False)
skip = MMGenListItemAttr('skip',str,typeconv=False,reassign_ok=True)

def age_disp(self,o,age_fmt): # TODO
return None

class EthereumTokenTwUnspentOutputs(EthereumTwUnspentOutputs):

disp_type = 'token'
Expand All @@ -322,7 +324,7 @@ def get_unspent_data(self):

class EthereumTwAddrList(TwAddrList):

def __init__(self,usr_addr_list,minconf,showempty,showbtcaddrs,all_labels,wallet=None):
def __init__(self,usr_addr_list,minconf,showempty,showbtcaddrs,all_labels,exact_age,wallet=None):

self.wallet = wallet or TrackingWallet(mode='w')
tw_dict = self.wallet.mmid_ordered_dict
Expand Down
2 changes: 2 additions & 0 deletions mmgen/protocol.py
Expand Up @@ -103,6 +103,7 @@ class BitcoinProtocol(MMGenObject):
sign_mode = 'daemon'
secp256k1_ge = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
privkey_len = 32
avg_bdi = int(9.7 * 60) # average block discovery interval (historical)

@classmethod
def addr_fmt_to_ver_bytes(cls,req_fmt,return_hex=False):
Expand Down Expand Up @@ -292,6 +293,7 @@ class LitecoinProtocol(BitcoinProtocol):
base_coin = 'LTC'
forks = []
bech32_hrp = 'ltc'
avg_bdi = 2 * 60

class LitecoinTestnetProtocol(LitecoinProtocol):
# addr ver nums same as Bitcoin testnet, except for 'p2sh'
Expand Down
23 changes: 20 additions & 3 deletions mmgen/rpc.py
Expand Up @@ -232,6 +232,7 @@ def do_fail(s):
'getblockchaininfo',
'getblockcount',
'getblockhash',
'getblockheader',
'getmempoolinfo',
'getmempoolentry',
'getnettotals',
Expand All @@ -257,6 +258,8 @@ class EthereumRPCConnection(RPCConnection):

auth = False
db_fs = ' host [{h}] port [{p}]\n'
_blockcount = None
_cur_date = None

rpcmethods = (
'eth_accounts',
Expand All @@ -268,7 +271,6 @@ class EthereumRPCConnection(RPCConnection):
'eth_gasPrice',
'eth_getBalance',
'eth_getBlockByHash',
'eth_getBlockByNumber',
'eth_getCode',
'eth_getTransactionByHash',
'eth_getTransactionReceipt',
Expand All @@ -285,6 +287,7 @@ class EthereumRPCConnection(RPCConnection):
'parity_composeTransaction',
'parity_gasCeilTarget',
'parity_gasFloorTarget',
'parity_getBlockHeaderByNumber',
'parity_localTransactions',
'parity_minGasPrice',
'parity_mode',
Expand All @@ -297,6 +300,19 @@ class EthereumRPCConnection(RPCConnection):
'parity_versionInfo',
)

# blockcount and cur_date require network RPC calls, so evaluate lazily
@property
def blockcount(self):
if self._blockcount == None:
self._blockcount = int(self.eth_blockNumber(),16)
return self._blockcount

@property
def cur_date(self):
if self._cur_date == None:
self._cur_date = int(self.parity_getBlockHeaderByNumber(hex(self.blockcount))['timestamp'],16)
return self._cur_date

class MoneroWalletRPCConnection(RPCConnection):

rpcmethods = (
Expand Down Expand Up @@ -390,7 +406,6 @@ def resolve_token_arg(token_arg):
conn = EthereumRPCConnection(
g.rpc_host or 'localhost',
g.rpc_port or g.proto.rpc_port)

conn.daemon_version = conn.parity_versionInfo()['version'] # fail immediately if daemon is geth
conn.coin_amt_type = str
g.chain = conn.parity_chain().replace(' ','_')
Expand All @@ -415,7 +430,7 @@ def init_daemon_bitcoind():

def check_chainfork_mismatch(conn):
block0 = conn.getblockhash(0)
latest = conn.getblockcount()
latest = conn.blockcount
try:
assert block0 == g.proto.block0,'Incorrect Genesis block for {}'.format(g.proto.__name__)
for fork in g.proto.forks:
Expand Down Expand Up @@ -446,6 +461,8 @@ def check_chaintype_mismatch():
from mmgen.regtest import MMGenRegtest
MMGenRegtest(g.coin).switch_user(('alice','bob')[g.bob],quiet=True)
conn.daemon_version = int(conn.getnetworkinfo()['version'])
conn.blockcount = conn.getblockcount()
conn.cur_date = conn.getblockheader(conn.getblockhash(conn.blockcount))['time']
conn.coin_amt_type = (float,str)[conn.daemon_version>=120000]
g.chain = conn.getblockchaininfo()['chain']
if g.chain != 'regtest': g.chain += 'net'
Expand Down
32 changes: 22 additions & 10 deletions mmgen/tool.py
Expand Up @@ -27,6 +27,9 @@

NL = ('\n','\r\n')[g.platform=='win']

def _options_annot_str(l):
return '(valid options: {})'.format(','.join(l))

def _create_call_sig(cmd,parsed=False):

m = getattr(MMGenToolCmd,cmd)
Expand Down Expand Up @@ -803,6 +806,8 @@ def gen_addr(self,mmgen_addr:str,wallet='',target='addr'):
ret = d.sec.wif if target=='wif' else d.addr
return ret

from mmgen.tw import TwAddrList,TwUnspentOutputs

class MMGenToolCmdRPC(MMGenToolCmdBase):
"tracking wallet commands using the JSON-RPC interface"

Expand All @@ -817,14 +822,18 @@ def listaddress(self,
pager = False,
showempty = True,
showbtcaddr = True,
age_fmt:'(valid options: days,confs)' = ''):
age_fmt: _options_annot_str(TwAddrList.age_fmts) = 'confs',
exact_age = False,
):
"list the specified MMGen address and its balance"
return self.listaddresses( mmgen_addrs = mmgen_addr,
minconf = minconf,
pager = pager,
showempty = showempty,
showbtcaddrs = showbtcaddr,
age_fmt = age_fmt)
age_fmt = age_fmt,
exact_age = exact_age,
)

def listaddresses( self,
mmgen_addrs:'(range or list)' = '',
Expand All @@ -834,7 +843,9 @@ def listaddresses( self,
showbtcaddrs = True,
all_labels = False,
sort:'(valid options: reverse,age)' = '',
age_fmt:'(valid options: days,confs)' = ''):
age_fmt: _options_annot_str(TwAddrList.age_fmts) = 'confs',
exact_age = False,
):
"list MMGen addresses and their balances"
show_age = bool(age_fmt)

Expand All @@ -853,28 +864,29 @@ def listaddresses( self,
usr_addr_list = [MMGenID('{}:{}'.format(a[0],i)) for i in AddrIdxList(a[1])]

rpc_init()
from mmgen.tw import TwAddrList
al = TwAddrList(usr_addr_list,minconf,showempty,showbtcaddrs,all_labels)
al = TwAddrList(usr_addr_list,minconf,showempty,showbtcaddrs,all_labels,exact_age)
if not al:
die(0,('No tracked addresses with balances!','No tracked addresses!')[showempty])
return al.format(showbtcaddrs,sort,show_age,age_fmt or 'days')
return al.format(showbtcaddrs,sort,show_age,age_fmt or 'confs')

def twview( self,
pager = False,
reverse = False,
wide = False,
minconf = 1,
sort = 'age',
age_fmt:'(valid options: days,confs)' = 'days',
show_mmid = True):
age_fmt: _options_annot_str(TwUnspentOutputs.age_fmts) = 'confs',
exact_age = False,
show_mmid = True,
wide_show_confs = True):
"view tracking wallet"
rpc_init()
from mmgen.tw import TwUnspentOutputs
twuo = TwUnspentOutputs(minconf=minconf)
twuo.do_sort(sort,reverse=reverse)
twuo.age_fmt = age_fmt
twuo.age_prec = 'exact' if exact_age else 'approx'
twuo.show_mmid = show_mmid
ret = twuo.format_for_printing(color=True) if wide else twuo.format_for_display()
ret = twuo.format_for_printing(color=True,show_confs=wide_show_confs) if wide else twuo.format_for_display()
del twuo.wallet
return ret

Expand Down

0 comments on commit b671453

Please sign in to comment.