Skip to content

Commit

Permalink
Curses-like scrolling UI for tracking wallet views
Browse files Browse the repository at this point in the history
A stationary header and footer with scrollable area in the middle creates
a much improved user experience compared to the old “dumb terminal” interface,
especially for large tracking wallets.

Scroll with either the Vi keys or up/down/arrow keys.

All tracking wallet views supported: unspent outputs, address list, tx history.

Activate with --scroll on the command line, or by setting the `scroll` option
in the config file.

This feature is entirely opt-in.  The old behavior continues to be supported
without alteration.

Sample invocation:

    $ mmgen-txcreate -qi --scroll

Interactive testing:

    # run the required regtest test dependencies:
    $ test/test.py -d regtest.view

    # test the scrolling UI interface interactively:
    $ PYTHONPATH=. MMGEN_TEST_SUITE=1 cmds/mmgen-tool --bob --scroll listaddresses interactive=1

    # when finished, stop the regtest daemon:
    $ test/stop-coin-daemons.py btc_rt
  • Loading branch information
mmgen committed Dec 7, 2022
1 parent 5b08b3d commit b26657f
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 24 deletions.
3 changes: 3 additions & 0 deletions mmgen/data/mmgen.cfg
Expand Up @@ -5,6 +5,9 @@
## User options ##
##################

# Uncomment to enable the curses-like scrolling UI for tracking wallet views
# scroll true

# Uncomment to suppress the GPL license prompt:
# no_license true

Expand Down
2 changes: 1 addition & 1 deletion mmgen/data/version
@@ -1 +1 @@
13.3.dev25
13.3.dev26
3 changes: 3 additions & 0 deletions mmgen/globalvars.py
Expand Up @@ -121,6 +121,7 @@ class GlobalContext(Lockable):
mnemonic_entry_modes = {}

# display:
scroll = False
columns = 0
color = bool(
( sys.stdout.isatty() and not os.getenv('MMGEN_TEST_SUITE_PEXPECT') ) or
Expand Down Expand Up @@ -183,6 +184,7 @@ class GlobalContext(Lockable):
'rpc_password',
'rpc_port',
'rpc_user',
'scroll',
'testnet',
'token' )

Expand Down Expand Up @@ -216,6 +218,7 @@ class GlobalContext(Lockable):
'rpc_password',
'rpc_port',
'rpc_user',
'scroll',
'subseeds',
'testnet',
'usr_randchars',
Expand Down
2 changes: 2 additions & 0 deletions mmgen/opts.py
Expand Up @@ -239,6 +239,8 @@ def do_fmt(set_data):
--, --token=t Specify an ERC20 token by address or symbol
--, --color=0|1 Disable or enable color output (enabled by default)
--, --columns=N Force N columns of output with certain commands
--, --scroll Use the curses-like scrolling interface for
tracking wallet views
--, --force-256-color Force 256-color output when color is enabled
--, --pager Pipe output of certain commands to pager (WIP)
--, --data-dir=path Specify {pnm} data directory location
Expand Down
7 changes: 7 additions & 0 deletions mmgen/proto/btc/tw/addresses.py
Expand Up @@ -28,6 +28,13 @@ class BitcoinTwAddresses(TwAddresses,BitcoinTwRPC):
Filters: show [E]mpty addrs, [u]sed addrs, all [L]abels
View/Print: pager [v]iew, [w]ide view, [p]rint
Actions: [q]uit view, r[e]draw, add [l]abel:
"""
prompt_scroll = """
Sort options: [a]mt, [A]ge, [M]mgen addr, [r]everse
Column options: toggle [D]ays/date/confs/block
Filters: show [E]mpty addrs, [u]sed addrs, all [L]abels
Scrolling: k=up, j=down, b=pgup, f=pgdown, g=top, G=bottom
Actions: [w]ide view, [q]uit, [p]rint, r[e]draw, add [l]abel:
"""
key_mappings = {
'a':'s_amt',
Expand Down
7 changes: 7 additions & 0 deletions mmgen/proto/btc/tw/txhistory.py
Expand Up @@ -235,6 +235,13 @@ class BitcoinTwTxHistory(TwTxHistory,BitcoinTwRPC):
Column opts: toggle [D]ays/date/confs/block, tx[i]d, [T]otal amt
View/Print: pager [v]iew, full [V]iew, screen [p]rint, full [P]rint
Filters/Actions: show [u]nconfirmed, [q]uit view, r[e]draw:
"""
prompt_scroll = """
Sorting: [t]xid, [a]mt, total a[m]t, [A]ge, block[n]um, [r]everse
Column opts: toggle [D]ays/date/confs/block, tx[i]d, [T]otal amt
View/Print: full [V]iew, screen [p]rint, full [P]rint
Scrolling: k=up, j=down, b=pgup, f=pgdown, g=top, G=bottom
Filters/Actions: show [u]nconfirmed, [q]uit view, r[e]draw:
"""
key_mappings = {
'A':'s_age',
Expand Down
6 changes: 6 additions & 0 deletions mmgen/proto/btc/tw/unspent.py
Expand Up @@ -35,6 +35,12 @@ class MMGenTwUnspentOutput(TwUnspentOutputs.MMGenTwUnspentOutput):
Display options: toggle [D]ays/date, show gr[o]up, show [m]mid
View options: pager [v]iew, [w]ide view
Actions: [q]uit view, [p]rint, r[e]draw, add [l]abel:
"""
prompt_scroll = """
Sort options: [t]xid, [a]mount, a[d]dr, [A]ge, [r]everse, [M]mid
Display options: toggle [D]ays/date, show gr[o]up, show [m]mid
Scrolling: k=up, j=down, b=pgup, f=pgdown, g=top, G=bottom
View/Actions: [w]ide view, [q]uit, [p]rint, r[e]draw, add [l]abel:
"""
key_mappings = {
't':'s_txid',
Expand Down
7 changes: 7 additions & 0 deletions mmgen/proto/eth/tw/addresses.py
Expand Up @@ -26,6 +26,13 @@ class EthereumTwAddresses(TwAddresses,EthereumTwView,EthereumTwRPC):
Filters: show [E]mpty addrs, all [L]abels
View/Print: pager [v]iew, [w]ide view, [p]rint
Actions: [q]uit view, r[e]draw, [D]elete addr, add [l]abel:
"""
prompt_scroll = """
Sort options: [a]mt, [M]mgen addr, [r]everse
Filters: show [E]mpty addrs, all [L]abels
View/Print: [w]ide view, [p]rint
Scrolling: k=up, j=down, b=pgup, f=pgdown, g=top, G=bottom
Actions: [q]uit view, r[e]draw, [D]elete addr, add [l]abel:
"""
key_mappings = {
'a':'s_amt',
Expand Down
7 changes: 7 additions & 0 deletions mmgen/proto/eth/tw/unspent.py
Expand Up @@ -50,6 +50,13 @@ class MMGenTwUnspentOutput(TwUnspentOutputs.MMGenTwUnspentOutput):
Display options: show [m]mgen addr, r[e]draw screen
View options: [q]uit view, [p]rint to file, [v]iew, [w]ide view
Actions: [D]elete addr, add [l]abel, [R]efresh balance:
"""
prompt_scroll = """
Sort options: [a]mount, a[d]dress, [r]everse, [M]mgen addr
Display options: show [m]mgen addr, r[e]draw screen
View options: [q]uit view, [p]rint to file, [w]ide view
Scrolling: k=up, j=down, b=pgup, f=pgdown, g=top, G=bottom
Actions: [D]elete addr, add [l]abel, [R]efresh balance:
"""
key_mappings = {
'a':'s_amt',
Expand Down
2 changes: 1 addition & 1 deletion mmgen/tw/addresses.py
Expand Up @@ -207,7 +207,7 @@ def gen_display(self,data,cw,fs,color,fmt_method):
for n,d in enumerate(data,1):
if id_save != d.al_id:
id_save = d.al_id
yield ''
yield ''.ljust(self.term_width)
yield fmt_method(n,d,cw,fs,color,yes,no)

async def set_dates(self,addrs):
Expand Down
2 changes: 1 addition & 1 deletion mmgen/tw/prune.py
Expand Up @@ -37,7 +37,7 @@ def gen_display(self,data,cw,fs,color,fmt_method):
for n,d in enumerate(data,1):
if id_save != d.al_id:
id_save = d.al_id
yield ''
yield ''.ljust(self.term_width)
yield (
gray(fmt_method(n,d,cw,fs,False,'Yes ','No ')) if d.tag else
fmt_method(n,d,cw,fs,True,yes,no) )
Expand Down

0 comments on commit b26657f

Please sign in to comment.