forked from esotericnonsense/bitcoind-ncurses
/
interface.py
96 lines (77 loc) · 3.08 KB
/
interface.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#!/usr/bin/env python
import curses
import sys
import gevent
import monitor
import process
import hotkey
import splash
import footer
def check_window_size(interface_queue, state, window, min_y, min_x):
# TODO: use SIGWINCH interrupt
if (state['y'], state['x']) != window.getmaxyx():
new_y, new_x = window.getmaxyx()
if (new_y < min_y) or (new_x < min_x):
interface_queue.put({ 'stop': "Window is too small - must be at least " + str(min_x) + "x" + str(min_y)})
if (state['y'], state['x']) != (-1, -1): # initialized
interface_queue.put({'resize': 1})
state['x'] = new_x
state['y'] = new_y
def init_curses():
window = curses.initscr()
curses.noecho() # prevents user input from being echoed
curses.curs_set(0) # make cursor invisible
curses.start_color()
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK)
curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLACK)
curses.init_pair(4, curses.COLOR_MAGENTA, curses.COLOR_BLACK)
curses.init_pair(5, curses.COLOR_YELLOW, curses.COLOR_BLACK)
window.timeout(50)
window.keypad(1) # interpret arrow keys, etc
return window
def init_state():
state = {
'mode': "splash",
'blocks': { 'cursor': 0, 'offset': 0 },
'networkhashps': {},
'estimatefee': {},
'console': { 'cbuffer': [], 'rbuffer': [], 'offset': 0 },
'x': -1,
'y': -1,
'history': { 'getnettotals': [] }
}
return state
def loop(block_viewer, state, window, interface_queue, rpcc, poller):
iterations = 0
while 1:
check_window_size(interface_queue, state, window, 12, 75) # min_y, min_x
error_message = process.queue(state, window, interface_queue)
if error_message:
return error_message # ends if stop command sent by rpc
gevent.sleep(0.0001) # TODO: Can we kill this?
if state['mode'] == "monitor":
if not iterations % 20:
monitor.draw_window(state, window)
footer.draw_window(state)
if hotkey.check(block_viewer, state, window, rpcc, poller): # poll for user input
break # returns 1 when quit key is pressed
iterations += 1
return False
def main(block_viewer, window, interface_queue, rpcc, poller, initial_mode=None):
error_message = False
rpcc.request("getnetworkinfo")
rpcc.request("getblockchaininfo")
try:
state = init_state()
splash.draw_window(state, window)
check_window_size(interface_queue, state, window, 12, 75) # min_y, min_x
if initial_mode:
hotkey.change_mode(state, window, initial_mode, poller)
error_message = loop(block_viewer, state, window, interface_queue, rpcc, poller)
finally: # restore sane terminal state, end RPC thread
curses.nocbreak()
curses.endwin()
if error_message:
sys.stderr.write("bitcoind-ncurses encountered an error\n")
sys.stderr.write("Message: " + error_message + "\n")