Exemplo n.º 1
0
class ElectrumGui:
    def __init__(self, config, daemon, plugins):
        self.config = config
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print("Wallet not found. try 'electrum-rvn create'")
            exit()
        if storage.is_encrypted():
            password = getpass.getpass('Password:'******'wallet_updated', 'network_updated', 'banner'])
        self.commands = [_("[h] - displays this help text"), \
                         _("[i] - display transaction history"), \
                         _("[o] - enter payment order"), \
                         _("[p] - print stored payment order"), \
                         _("[s] - send stored payment order"), \
                         _("[r] - show own receipt addresses"), \
                         _("[c] - display contacts"), \
                         _("[b] - print server banner"), \
                         _("[q] - quit") ]
        self.num_commands = len(self.commands)

    def on_network(self, event, *args):
        if event in ['wallet_updated', 'network_updated']:
            self.updated()
        elif event == 'banner':
            self.print_banner()

    def main_command(self):
        self.print_balance()
        c = input("enter command: ")
        if c == "h": self.print_commands()
        elif c == "i": self.print_history()
        elif c == "o": self.enter_order()
        elif c == "p": self.print_order()
        elif c == "s": self.send_order()
        elif c == "r": self.print_addresses()
        elif c == "c": self.print_contacts()
        elif c == "b": self.print_banner()
        elif c == "n": self.network_dialog()
        elif c == "e": self.settings_dialog()
        elif c == "q": self.done = 1
        else: self.print_commands()

    def updated(self):
        s = self.get_balance()
        if s != self.last_balance:
            print(s)
        self.last_balance = s
        return True

    def print_commands(self):
        self.print_list(self.commands, "Available commands")

    def print_history(self):
        width = [20, 40, 14, 14]
        delta = (80 - sum(width) - 4) / 3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%" \
        + "%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"
        messages = []

        for tx_hash, tx_mined_status, delta, balance in reversed(
                self.wallet.get_history()):
            if tx_mined_status.conf:
                timestamp = tx_mined_status.timestamp
                try:
                    time_str = datetime.datetime.fromtimestamp(
                        timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "unknown"
            else:
                time_str = 'unconfirmed'

            label = self.wallet.get_label(tx_hash)
            messages.append(
                format_str %
                (time_str, label, format_satoshis(delta, whitespaces=True),
                 format_satoshis(balance, whitespaces=True)))

        self.print_list(
            messages[::-1], format_str %
            (_("Date"), _("Description"), _("Amount"), _("Balance")))

    def print_balance(self):
        print(self.get_balance())

    def get_balance(self):
        if self.wallet.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else:
                c, u, x = self.wallet.get_balance()
                msg = _("Balance") + ": %f  " % (Decimal(c) / COIN)
                if u:
                    msg += "  [%f unconfirmed]" % (Decimal(u) / COIN)
                if x:
                    msg += "  [%f unmatured]" % (Decimal(x) / COIN)
        else:
            msg = _("Not connected")

        return (msg)

    def print_contacts(self):
        messages = map(lambda x: "%20s   %45s " % (x[0], x[1][1]),
                       self.contacts.items())
        self.print_list(messages, "%19s  %25s " % ("Key", "Value"))

    def print_addresses(self):
        messages = map(
            lambda addr: "%30s    %30s       " %
            (addr, self.wallet.labels.get(addr, "")),
            self.wallet.get_addresses())
        self.print_list(messages, "%19s  %25s " % ("Address", "Label"))

    def print_order(self):
        print("send order to " + self.str_recipient + ", amount: " + self.str_amount \
              + "\nfee: " + self.str_fee + ", desc: " + self.str_description)

    def enter_order(self):
        self.str_recipient = input("Pay to: ")
        self.str_description = input("Description : ")
        self.str_amount = input("Amount: ")
        self.str_fee = input("Fee: ")

    def send_order(self):
        self.do_send()

    def print_banner(self):
        for i, x in enumerate(self.wallet.network.banner.split('\n')):
            print(x)

    def print_list(self, lst, firstline):
        lst = list(lst)
        self.maxpos = len(lst)
        if not self.maxpos: return
        print(firstline)
        for i in range(self.maxpos):
            msg = lst[i] if i < len(lst) else ""
            print(msg)

    def main(self):
        while self.done == 0:
            self.main_command()

    def do_send(self):
        if not is_address(self.str_recipient):
            print(_('Invalid Bitcoin address'))
            return
        try:
            amount = int(Decimal(self.str_amount) * COIN)
        except Exception:
            print(_('Invalid Amount'))
            return
        try:
            fee = int(Decimal(self.str_fee) * COIN)
        except Exception:
            print(_('Invalid Fee'))
            return

        if self.wallet.has_password():
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        c = ""
        while c != "y":
            c = input("ok to send (y/n)?")
            if c == "n": return

        try:
            tx = self.wallet.mktx(
                [TxOutput(TYPE_ADDRESS, self.str_recipient, amount)], password,
                self.config, fee)
        except Exception as e:
            print(str(e))
            return

        if self.str_description:
            self.wallet.labels[tx.txid()] = self.str_description

        print(_("Please wait..."))
        try:
            self.network.run_from_another_thread(
                self.network.broadcast_transaction(tx))
        except Exception as e:
            print(repr(e))
        else:
            print(_('Payment sent.'))
            #self.do_clear()
            #self.update_contacts_tab()

    def network_dialog(self):
        print(
            "use 'electrum setconfig server/proxy' to change your network settings"
        )
        return True

    def settings_dialog(self):
        print("use 'electrum setconfig' to change your settings")
        return True

    def password_dialog(self):
        return getpass.getpass()

#   XXX unused

    def run_receive_tab(self, c):
        #if c == 10:
        #    out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"])
        return

    def run_contacts_tab(self, c):
        pass
Exemplo n.º 2
0
class ElectrumGui:

    def __init__(self, config, daemon, plugins):
        self.config = config
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print("Wallet not found. try 'electrum create'")
            exit()
        if storage.is_encrypted():
            password = getpass.getpass('Password:'******'updated', 'banner'])
        self.commands = [_("[h] - displays this help text"), \
                         _("[i] - display transaction history"), \
                         _("[o] - enter payment order"), \
                         _("[p] - print stored payment order"), \
                         _("[s] - send stored payment order"), \
                         _("[r] - show own receipt addresses"), \
                         _("[c] - display contacts"), \
                         _("[b] - print server banner"), \
                         _("[q] - quit") ]
        self.num_commands = len(self.commands)

    def on_network(self, event, *args):
        if event == 'updated':
            self.updated()
        elif event == 'banner':
            self.print_banner()

    def main_command(self):
        self.print_balance()
        c = input("enter command: ")
        if c == "h" : self.print_commands()
        elif c == "i" : self.print_history()
        elif c == "o" : self.enter_order()
        elif c == "p" : self.print_order()
        elif c == "s" : self.send_order()
        elif c == "r" : self.print_addresses()
        elif c == "c" : self.print_contacts()
        elif c == "b" : self.print_banner()
        elif c == "n" : self.network_dialog()
        elif c == "e" : self.settings_dialog()
        elif c == "q" : self.done = 1
        else: self.print_commands()

    def updated(self):
        s = self.get_balance()
        if s != self.last_balance:
            print(s)
        self.last_balance = s
        return True

    def print_commands(self):
        self.print_list(self.commands, "Available commands")

    def print_history(self):
        width = [20, 40, 14, 14]
        delta = (80 - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%" \
        + "%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"
        b = 0
        messages = []

        for item in self.wallet.get_history():
            tx_hash, confirmations, value, timestamp, balance = item
            if confirmations:
                try:
                    time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "unknown"
            else:
                time_str = 'unconfirmed'

            label = self.wallet.get_label(tx_hash)
            messages.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) )

        self.print_list(messages[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance")))


    def print_balance(self):
        print(self.get_balance())

    def get_balance(self):
        if self.wallet.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _( "Synchronizing..." )
            else:
                c, u, x =  self.wallet.get_balance()
                msg = _("Balance")+": %f  "%(Decimal(c) / COIN)
                if u:
                    msg += "  [%f unconfirmed]"%(Decimal(u) / COIN)
                if x:
                    msg += "  [%f unmatured]"%(Decimal(x) / COIN)
        else:
                msg = _( "Not connected" )

        return(msg)


    def print_contacts(self):
        messages = map(lambda x: "%20s   %45s "%(x[0], x[1][1]), self.contacts.items())
        self.print_list(messages, "%19s  %25s "%("Key", "Value"))

    def print_addresses(self):
        messages = map(lambda addr: "%30s    %30s       "%(addr, self.wallet.labels.get(addr,"")), self.wallet.get_addresses())
        self.print_list(messages, "%19s  %25s "%("Address", "Label"))

    def print_order(self):
        print("send order to " + self.str_recipient + ", amount: " + self.str_amount \
              + "\nfee: " + self.str_fee + ", desc: " + self.str_description)

    def enter_order(self):
        self.str_recipient = input("Pay to: ")
        self.str_description = input("Description : ")
        self.str_amount = input("Amount: ")
        self.str_fee = input("Fee: ")

    def send_order(self):
        self.do_send()

    def print_banner(self):
        for i, x in enumerate( self.wallet.network.banner.split('\n') ):
            print( x )

    def print_list(self, list, firstline):
        self.maxpos = len(list)
        if not self.maxpos: return
        print(firstline)
        for i in range(self.maxpos):
            msg = list[i] if i < len(list) else ""
            print(msg)


    def main(self):
        while self.done == 0: self.main_command()

    def do_send(self):
        if not is_address(self.str_recipient):
            print(_('Invalid Bitcoin address'))
            return
        try:
            amount = int(Decimal(self.str_amount) * COIN)
        except Exception:
            print(_('Invalid Amount'))
            return
        try:
            fee = int(Decimal(self.str_fee) * COIN)
        except Exception:
            print(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        c = ""
        while c != "y":
            c = input("ok to send (y/n)?")
            if c == "n": return

        try:
            tx = self.wallet.mktx([(TYPE_ADDRESS, self.str_recipient, amount)], password, self.config, fee)
        except Exception as e:
            print(str(e))
            return

        if self.str_description:
            self.wallet.labels[tx.hash()] = self.str_description

        print(_("Please wait..."))
        status, msg = self.network.broadcast(tx)

        if status:
            print(_('Payment sent.'))
            #self.do_clear()
            #self.update_contacts_tab()
        else:
            print(_('Error'))

    def network_dialog(self):
        print("use 'electrum setconfig server/proxy' to change your network settings")
        return True


    def settings_dialog(self):
        print("use 'electrum setconfig' to change your settings")
        return True

    def password_dialog(self):
        return getpass.getpass()


#   XXX unused

    def run_receive_tab(self, c):
        #if c == 10:
        #    out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"])
        return

    def run_contacts_tab(self, c):
        pass
Exemplo n.º 3
0
class ElectrumGui:

    def __init__(self, config, network):

        self.config = config
        self.network = network
        storage = WalletStorage(config)
        if not storage.file_exists:
            print "Wallet not found. try 'electrum create'"
            exit()

        self.wallet = Wallet(storage)
        self.wallet.start_threads(self.network)

        locale.setlocale(locale.LC_ALL, '')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None
       
        if self.network: 
            self.network.register_callback('updated', self.update)
            self.network.register_callback('connected', self.refresh)
            self.network.register_callback('disconnected', self.refresh)
            self.network.register_callback('disconnecting', self.refresh)

        self.tab_names = [_("History"), _("Send"), _("Receive"), _("Contacts"), _("Wall")]
        self.num_tabs = len(self.tab_names)


    def set_cursor(self, x):
        try:
            curses.curs_set(x)
        except Exception:
            pass

    def restore_or_create(self):
        pass

    def verify_seed(self):
        pass
    
    def get_string(self, y, x):
        self.set_cursor(1)
        curses.echo()
        self.stdscr.addstr( y, x, " "*20, curses.A_REVERSE)
        s = self.stdscr.getstr(y,x)
        curses.noecho()
        self.set_cursor(0)
        return s

    def update(self):
        self.update_history()
        if self.tab == 0: 
            self.print_history()
        self.refresh()

    def print_history(self):

        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        if self.history is None:
            self.update_history()

        self.print_list(self.history[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance")))

    def update_history(self):
        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        b = 0 
        self.history = []

        for item in self.wallet.get_tx_history():
            tx_hash, conf, is_mine, value, fee, balance, timestamp = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp( timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "------"
            else:
                time_str = 'pending'

            label, is_default_label = self.wallet.get_label(tx_hash)
            self.history.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) )


    def print_balance(self):
        if not self.network:
            msg = _("Offline")
        elif self.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else: 
                c, u =  self.wallet.get_balance()
                msg = _("Balance")+": %f  "%(Decimal( c ) / 100000000)
                if u: msg += "  [%f unconfirmed]"%(Decimal( u ) / 100000000)
        else:
            msg = _("Not connected")
            
        self.stdscr.addstr( self.maxy -1, 3, msg)

        for i in range(self.num_tabs):
            self.stdscr.addstr( 0, 2 + 2*i + len(''.join(self.tab_names[0:i])), ' '+self.tab_names[i]+' ', curses.A_BOLD if self.tab == i else 0)
            
        self.stdscr.addstr( self.maxy -1, self.maxx-30, ' '.join([_("Settings"), _("Network"), _("Quit")]))


    def print_contacts(self):
        messages = map(lambda addr: "%30s    %30s       "%(addr, self.wallet.labels.get(addr,"")), self.wallet.addressbook)
        self.print_list(messages, "%19s  %25s "%("Address", "Label"))

    def print_receive(self):
        fmt = "%-35s  %-30s"
        messages = map(lambda addr: fmt % (addr, self.wallet.labels.get(addr,"")), self.wallet.addresses())
        self.print_list(messages,   fmt % ("Address", "Label"))

    def print_edit_line(self, y, label, text, index, size):
        text += " "*(size - len(text) )
        self.stdscr.addstr( y, 2, label)
        self.stdscr.addstr( y, 15, text, curses.A_REVERSE if self.pos%6==index else curses.color_pair(1))

    def print_send_tab(self):
        self.stdscr.clear()
        self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40)
        self.print_edit_line(5, _("Description"), self.str_description, 1, 40)
        self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15)
        self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15)
        self.stdscr.addstr( 12, 15, _("[Send]"), curses.A_REVERSE if self.pos%6==4 else curses.color_pair(2))
        self.stdscr.addstr( 12, 25, _("[Clear]"), curses.A_REVERSE if self.pos%6==5 else curses.color_pair(2))

    def print_banner(self):
        if self.network:
            self.print_list( self.network.banner.split('\n'))

    def print_list(self, list, firstline = None):
        self.maxpos = len(list)
        if not self.maxpos: return
        if firstline:
            firstline += " "*(self.maxx -2 - len(firstline))
            self.stdscr.addstr( 1, 1, firstline )
        for i in range(self.maxy-4):
            msg = list[i] if i < len(list) else ""
            msg += " "*(self.maxx - 2 - len(msg))
            m = msg[0:self.maxx - 2]
            m = m.encode(self.encoding)
            self.stdscr.addstr( i+2, 1, m, curses.A_REVERSE if i == (self.pos % self.maxpos) else 0)

    def refresh(self):
        if self.tab == -1: return
        self.stdscr.border(0)
        self.print_balance()
        self.stdscr.refresh()

    def main_command(self):
        c = self.stdscr.getch()
        print c
        if   c == curses.KEY_RIGHT: self.tab = (self.tab + 1)%self.num_tabs
        elif c == curses.KEY_LEFT: self.tab = (self.tab - 1)%self.num_tabs
        elif c == curses.KEY_DOWN: self.pos +=1
        elif c == curses.KEY_UP: self.pos -= 1
        elif c == 9: self.pos +=1 # tab
        elif curses.unctrl(c) in ['^W', '^C', '^X', '^Q']: self.tab = -1
        elif curses.unctrl(c) in ['^N']: self.network_dialog()
        elif curses.unctrl(c) == '^S': self.settings_dialog()
        else: return c
        if self.pos<0: self.pos=0
        if self.pos>=self.maxpos: self.pos=self.maxpos - 1

    def run_tab(self, i, print_func, exec_func):
        while self.tab == i:
            self.stdscr.clear()
            print_func()
            self.refresh()
            c = self.main_command()
            if c: exec_func(c)


    def run_history_tab(self, c):
        if c == 10:
            out = self.run_popup('',["blah","foo"])
            

    def edit_str(self, target, c, is_num=False):
        # detect backspace
        if c in [8, 127, 263] and target:
            target = target[:-1]
        elif not is_num or curses.unctrl(c) in '0123456789.':
            target += curses.unctrl(c)
        return target


    def run_send_tab(self, c):
        if self.pos%6 == 0:
            self.str_recipient = self.edit_str(self.str_recipient, c)
        if self.pos%6 == 1:
            self.str_description = self.edit_str(self.str_description, c)
        if self.pos%6 == 2:
            self.str_amount = self.edit_str(self.str_amount, c, True)
        elif self.pos%6 == 3:
            self.str_fee = self.edit_str(self.str_fee, c, True)
        elif self.pos%6==4:
            if c == 10: self.do_send()
        elif self.pos%6==5:
            if c == 10: self.do_clear()

            
    def run_receive_tab(self, c):
        if c == 10:
            out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"])
            
    def run_contacts_tab(self, c):
        if c == 10 and self.wallet.addressbook:
            out = self.run_popup('Adress', ["Copy", "Pay to", "Edit label", "Delete"]).get('button')
            address = self.wallet.addressbook[self.pos%len(self.wallet.addressbook)]
            if out == "Pay to":
                self.tab = 1
                self.str_recipient = address 
                self.pos = 2
            elif out == "Edit label":
                s = self.get_string(6 + self.pos, 18)
                if s:
                    self.wallet.labels[address] = s
            
    def run_banner_tab(self, c):
        self.show_message(repr(c))
        pass

    def main(self,url):

        tty.setraw(sys.stdin)
        while self.tab != -1:
            self.run_tab(0, self.print_history, self.run_history_tab)
            self.run_tab(1, self.print_send_tab, self.run_send_tab)
            self.run_tab(2, self.print_receive, self.run_receive_tab)
            self.run_tab(3, self.print_contacts, self.run_contacts_tab)
            self.run_tab(4, self.print_banner, self.run_banner_tab)

        tty.setcbreak(sys.stdin)
        curses.nocbreak()
        self.stdscr.keypad(0)
        curses.echo()
        curses.endwin()


    def do_clear(self):
        self.str_amount = ''
        self.str_recipient = ''
        self.str_fee = ''
        self.str_description = ''

    def do_send(self):
        if not is_valid(self.str_recipient):
            self.show_message(_('Invalid Reddcoin address'))
            return
        try:
            amount = int( Decimal( self.str_amount) * 100000000 )
        except Exception:
            self.show_message(_('Invalid Amount'))
            return
        try:
            fee = int( Decimal( self.str_fee) * 100000000 )
        except Exception:
            self.show_message(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        try:
            tx = self.wallet.mktx( [(self.str_recipient, amount)], password, fee)
        except Exception as e:
            self.show_message(str(e))
            return
            
        if self.str_description: 
            self.wallet.labels[tx.hash()] = self.str_description

        h = self.wallet.send_tx(tx)
        self.show_message(_("Please wait..."), getchar=False)
        self.wallet.tx_event.wait()
        status, msg = self.wallet.receive_tx( h, tx )

        if status:
            self.show_message(_('Payment sent.'))
            self.do_clear()
            #self.update_contacts_tab()
        else:
            self.show_message(_('Error'))


    def show_message(self, message, getchar = True):
        w = self.w
        w.clear()
        w.border(0)
        for i, line in enumerate(message.split('\n')):
            w.addstr(2+i,2,line)
        w.refresh()
        if getchar: c = self.stdscr.getch()


    def run_popup(self, title, items):
        return self.run_dialog(title, map(lambda x: {'type':'button','label':x}, items), interval=1, y_pos = self.pos+3)


    def network_dialog(self):
        if not self.network: return
        auto_connect = self.network.config.get('auto_cycle')
        host, port, protocol = self.network.default_server.split(':')
        srv = 'auto-connect' if auto_connect else self.network.default_server

        out = self.run_dialog('Network', [
            {'label':'server', 'type':'str', 'value':srv},
            {'label':'proxy', 'type':'str', 'value':self.config.get('proxy', '')},
            ], buttons = 1)
        if out:
            if out.get('server'):
                server = out.get('server')
                auto_connect = server == 'auto-connect'
                if not auto_connect:
                    try:
                        host, port, protocol = server.split(':')
                    except Exception:
                        self.show_message("Error:" + server + "\nIn doubt, type \"auto-connect\"")
                        return False

                if out.get('proxy'):
                    proxy = self.parse_proxy_options(out.get('proxy'))
                else:
                    proxy = None

                self.network.set_parameters(host, port, protocol, proxy, auto_connect)
                


    def settings_dialog(self):
        out = self.run_dialog('Settings', [
            {'label':'Default GUI', 'type':'list', 'choices':['classic','lite','gtk','text'], 'value':self.config.get('gui')},
            {'label':'Default fee', 'type':'satoshis', 'value': format_satoshis(self.wallet.fee).strip() }
            ], buttons = 1)
        if out:
            if out.get('Default GUI'):
                self.config.set_key('gui', out['Default GUI'], True)
            if out.get('Default fee'):
                fee = int ( Decimal( out['Default fee']) *10000000 )
                self.config.set_key('fee_per_kb', fee, True)


    def password_dialog(self):
        out = self.run_dialog('Password', [
            {'label':'Password', 'type':'password', 'value':''}
            ], buttons = 1)
        return out.get('Password')
        

    def run_dialog(self, title, items, interval=2, buttons=None, y_pos=3):
        self.popup_pos = 0
        
        self.w = curses.newwin( 5 + len(items)*interval + (2 if buttons else 0), 50, y_pos, 5)
        w = self.w
        out = {}
        while True:
            w.clear()
            w.border(0)
            w.addstr( 0, 2, title)

            num = len(items)

            numpos = num
            if buttons: numpos += 2

            for i in range(num):
                item = items[i]
                label = item.get('label')
                if item.get('type') == 'list':
                    value = item.get('value','')
                elif item.get('type') == 'satoshis':
                    value = item.get('value','')
                elif item.get('type') == 'str':
                    value = item.get('value','')
                elif item.get('type') == 'password':
                    value = '*'*len(item.get('value',''))
                else:
                    value = ''

                if len(value)<20: value += ' '*(20-len(value))

                if item.has_key('value'):
                    w.addstr( 2+interval*i, 2, label)
                    w.addstr( 2+interval*i, 15, value, curses.A_REVERSE if self.popup_pos%numpos==i else curses.color_pair(1) )
                else:
                    w.addstr( 2+interval*i, 2, label, curses.A_REVERSE if self.popup_pos%numpos==i else 0)

            if buttons:
                w.addstr( 5+interval*i, 10, "[  ok  ]",     curses.A_REVERSE if self.popup_pos%numpos==(numpos-2) else curses.color_pair(2))
                w.addstr( 5+interval*i, 25, "[cancel]", curses.A_REVERSE if self.popup_pos%numpos==(numpos-1) else curses.color_pair(2))
                
            w.refresh()

            c = self.stdscr.getch()
            if c in [ord('q'), 27]: break
            elif c in [curses.KEY_LEFT, curses.KEY_UP]: self.popup_pos -= 1
            elif c in [curses.KEY_RIGHT, curses.KEY_DOWN]: self.popup_pos +=1
            else:
                i = self.popup_pos%numpos
                if buttons and c==10:
                    if i == numpos-2:
                        return out
                    elif i == numpos -1:
                        return {}

                item = items[i]
                _type = item.get('type')

                if _type == 'str':
                    item['value'] = self.edit_str(item['value'], c)
                    out[item.get('label')] = item.get('value')

                elif _type == 'password':
                    item['value'] = self.edit_str(item['value'], c)
                    out[item.get('label')] = item ['value']

                elif _type == 'satoshis':
                    item['value'] = self.edit_str(item['value'], c, True)
                    out[item.get('label')] = item.get('value')

                elif _type == 'list':
                    choices = item.get('choices')
                    try:
                        j = choices.index(item.get('value'))
                    except Exception:
                        j = 0
                    new_choice = choices[(j + 1)% len(choices)]
                    item['value'] = new_choice
                    out[item.get('label')] = item.get('value')
                    
                elif _type == 'button':
                    out['button'] = item.get('label')
                    break

        return out
Exemplo n.º 4
0
class ElectrumGui:
    def __init__(self, config, network):

        self.config = config
        self.network = network
        storage = WalletStorage(config)
        if not storage.file_exists:
            print "Wallet not found. try 'electrum create'"
            exit()

        self.wallet = Wallet(storage)
        self.wallet.start_threads(network)

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None

        self.network.register_callback('updated', self.update)
        self.network.register_callback('connected', self.refresh)
        self.network.register_callback('disconnected', self.refresh)
        self.network.register_callback('disconnecting', self.refresh)
        self.tab_names = [
            _("History"),
            _("Send"),
            _("Receive"),
            _("Contacts"),
            _("Wall")
        ]
        self.num_tabs = len(self.tab_names)

    def set_cursor(self, x):
        try:
            curses.curs_set(x)
        except:
            pass

    def restore_or_create(self):
        pass

    def verify_seed(self):
        pass

    def get_string(self, y, x):
        self.set_cursor(1)
        curses.echo()
        self.stdscr.addstr(y, x, " " * 20, curses.A_REVERSE)
        s = self.stdscr.getstr(y, x)
        curses.noecho()
        self.set_cursor(0)
        return s

    def update(self):
        self.update_history()
        if self.tab == 0:
            self.print_history()
        self.refresh()

    def print_history(self):

        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4) / 3
        format_str = "%" + "%d" % width[0] + "s" + "%" + "%d" % (
            width[1] + delta) + "s" + "%" + "%d" % (
                width[2] + delta) + "s" + "%" + "%d" % (width[3] + delta) + "s"

        if self.history is None:
            self.update_history()

        self.print_list(
            self.history[::-1], format_str %
            (_("Date"), _("Description"), _("Amount"), _("Balance")))

    def update_history(self):
        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4) / 3
        format_str = "%" + "%d" % width[0] + "s" + "%" + "%d" % (
            width[1] + delta) + "s" + "%" + "%d" % (
                width[2] + delta) + "s" + "%" + "%d" % (width[3] + delta) + "s"

        b = 0
        self.history = []

        for item in self.wallet.get_tx_history():
            tx_hash, conf, is_mine, value, fee, balance, timestamp = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp(
                        timestamp).isoformat(' ')[:-3]
                except:
                    time_str = "------"
            else:
                time_str = 'pending'

            label, is_default_label = self.wallet.get_label(tx_hash)
            self.history.append(
                format_str %
                (time_str, label, format_satoshis(value, whitespaces=True),
                 format_satoshis(balance, whitespaces=True)))

    def print_balance(self):
        if self.network.interface and self.network.interface.is_connected:
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else:
                c, u = self.wallet.get_balance()
                msg = _("Balance") + ": %f  " % (Decimal(c) / 100000000)
                if u: msg += "  [%f unconfirmed]" % (Decimal(u) / 100000000)
        else:
            msg = _("Not connected")

        self.stdscr.addstr(self.maxy - 1, 3, msg)

        for i in range(self.num_tabs):
            self.stdscr.addstr(0,
                               2 + 2 * i + len(''.join(self.tab_names[0:i])),
                               ' ' + self.tab_names[i] + ' ',
                               curses.A_BOLD if self.tab == i else 0)

        self.stdscr.addstr(self.maxy - 1, self.maxx - 30,
                           ' '.join([_("Settings"),
                                     _("Network"),
                                     _("Quit")]))

    def print_contacts(self):
        messages = map(
            lambda addr: "%30s    %30s       " %
            (addr, self.wallet.labels.get(addr, "")), self.wallet.addressbook)
        self.print_list(messages, "%19s  %25s " % ("Address", "Label"))

    def print_receive(self):
        messages = map(
            lambda addr: "%30s    %30s       " %
            (addr, self.wallet.labels.get(addr, "")), self.wallet.addresses())
        self.print_list(messages, "%19s  %25s " % ("Address", "Label"))

    def print_edit_line(self, y, label, text, index, size):
        text += " " * (size - len(text))
        self.stdscr.addstr(y, 2, label)
        self.stdscr.addstr(
            y, 15, text, curses.A_REVERSE if self.pos %
            6 == index else curses.color_pair(1))

    def print_send_tab(self):
        self.stdscr.clear()
        self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40)
        self.print_edit_line(5, _("Description"), self.str_description, 1, 40)
        self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15)
        self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15)
        self.stdscr.addstr(
            12, 15, _("[Send]"),
            curses.A_REVERSE if self.pos % 6 == 4 else curses.color_pair(2))
        self.stdscr.addstr(
            12, 25, _("[Clear]"),
            curses.A_REVERSE if self.pos % 6 == 5 else curses.color_pair(2))

    def print_banner(self):
        self.print_list(self.network.banner.split('\n'))

    def print_list(self, list, firstline=None):
        self.maxpos = len(list)
        if not self.maxpos: return
        if firstline:
            firstline += " " * (self.maxx - 2 - len(firstline))
            self.stdscr.addstr(1, 1, firstline)
        for i in range(self.maxy - 4):
            msg = list[i] if i < len(list) else ""
            msg += " " * (self.maxx - 2 - len(msg))
            self.stdscr.addstr(
                i + 2, 1, msg[0:self.maxx - 2],
                curses.A_REVERSE if i == (self.pos % self.maxpos) else 0)

    def refresh(self):
        if self.tab == -1: return
        self.stdscr.border(0)
        self.print_balance()
        self.stdscr.refresh()

    def main_command(self):
        c = self.stdscr.getch()
        print c
        if c == curses.KEY_RIGHT: self.tab = (self.tab + 1) % self.num_tabs
        elif c == curses.KEY_LEFT: self.tab = (self.tab - 1) % self.num_tabs
        elif c == curses.KEY_DOWN: self.pos += 1
        elif c == curses.KEY_UP: self.pos -= 1
        elif c == 9: self.pos += 1  # tab
        elif curses.unctrl(c) in ['^W', '^C', '^X', '^Q']: self.tab = -1
        elif curses.unctrl(c) in ['^N']: self.network_dialog()
        elif curses.unctrl(c) == '^S': self.settings_dialog()
        else: return c
        if self.pos < 0: self.pos = 0
        if self.pos >= self.maxpos: self.pos = self.maxpos - 1

    def run_tab(self, i, print_func, exec_func):
        while self.tab == i:
            self.stdscr.clear()
            print_func()
            self.refresh()
            c = self.main_command()
            if c: exec_func(c)

    def run_history_tab(self, c):
        if c == 10:
            out = self.run_popup('', ["blah", "foo"])

    def edit_str(self, target, c, is_num=False):
        # detect backspace
        if c in [8, 127, 263] and target:
            target = target[:-1]
        elif not is_num or curses.unctrl(c) in '0123456789.':
            target += curses.unctrl(c)
        return target

    def run_send_tab(self, c):
        if self.pos % 6 == 0:
            self.str_recipient = self.edit_str(self.str_recipient, c)
        if self.pos % 6 == 1:
            self.str_description = self.edit_str(self.str_description, c)
        if self.pos % 6 == 2:
            self.str_amount = self.edit_str(self.str_amount, c, True)
        elif self.pos % 6 == 3:
            self.str_fee = self.edit_str(self.str_fee, c, True)
        elif self.pos % 6 == 4:
            if c == 10: self.do_send()
        elif self.pos % 6 == 5:
            if c == 10: self.do_clear()

    def run_receive_tab(self, c):
        if c == 10:
            out = self.run_popup('Address',
                                 ["Edit label", "Freeze", "Prioritize"])

    def run_contacts_tab(self, c):
        if c == 10 and self.wallet.addressbook:
            out = self.run_popup(
                'Adress',
                ["Copy", "Pay to", "Edit label", "Delete"]).get('button')
            address = self.wallet.addressbook[self.pos %
                                              len(self.wallet.addressbook)]
            if out == "Pay to":
                self.tab = 1
                self.str_recipient = address
                self.pos = 2
            elif out == "Edit label":
                s = self.get_string(6 + self.pos, 18)
                if s:
                    self.wallet.labels[address] = s

    def run_banner_tab(self, c):
        self.show_message(repr(c))
        pass

    def main(self, url):

        tty.setraw(sys.stdin)
        while self.tab != -1:
            self.run_tab(0, self.print_history, self.run_history_tab)
            self.run_tab(1, self.print_send_tab, self.run_send_tab)
            self.run_tab(2, self.print_receive, self.run_receive_tab)
            self.run_tab(3, self.print_contacts, self.run_contacts_tab)
            self.run_tab(4, self.print_banner, self.run_banner_tab)

        tty.setcbreak(sys.stdin)
        curses.nocbreak()
        self.stdscr.keypad(0)
        curses.echo()
        curses.endwin()

    def do_clear(self):
        self.str_amount = ''
        self.str_recipient = ''
        self.str_fee = ''
        self.str_description = ''

    def do_send(self):
        if not is_valid(self.str_recipient):
            self.show_message(_('Invalid Bitcoin address'))
            return
        try:
            amount = int(Decimal(self.str_amount) * 100000000)
        except:
            self.show_message(_('Invalid Amount'))
            return
        try:
            fee = int(Decimal(self.str_fee) * 100000000)
        except:
            self.show_message(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        try:
            tx = self.wallet.mktx([(self.str_recipient, amount)], password,
                                  fee)
        except BaseException, e:
            self.show_message(str(e))
            return

        if self.str_description:
            self.wallet.labels[tx.hash()] = self.str_description

        h = self.wallet.send_tx(tx)
        self.show_message(_("Please wait..."), getchar=False)
        self.wallet.tx_event.wait()
        status, msg = self.wallet.receive_tx(h)

        if status:
            self.show_message(_('Payment sent.'))
            self.do_clear()
            #self.update_contacts_tab()
        else:
            self.show_message(_('Error'))
Exemplo n.º 5
0
class ElectrumGui:
    def __init__(self, config, daemon, plugins):

        self.config = config
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print "Wallet not found. try 'electrum create'"
            exit()

        self.wallet = Wallet(storage)
        self.wallet.start_threads(self.network)
        self.contacts = StoreDict(self.config, 'contacts')

        locale.setlocale(locale.LC_ALL, '')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None

        if self.network:
            self.network.register_callback(self.update, ['updated'])

        self.tab_names = [
            _("History"),
            _("Send"),
            _("Receive"),
            _("Addresses"),
            _("Contacts"),
            _("Banner")
        ]
        self.num_tabs = len(self.tab_names)

    def set_cursor(self, x):
        try:
            curses.curs_set(x)
        except Exception:
            pass

    def restore_or_create(self):
        pass

    def verify_seed(self):
        pass

    def get_string(self, y, x):
        self.set_cursor(1)
        curses.echo()
        self.stdscr.addstr(y, x, " " * 20, curses.A_REVERSE)
        s = self.stdscr.getstr(y, x)
        curses.noecho()
        self.set_cursor(0)
        return s

    def update(self, event):
        self.update_history()
        if self.tab == 0:
            self.print_history()
        self.refresh()

    def print_history(self):

        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4) / 3
        format_str = "%" + "%d" % width[0] + "s" + "%" + "%d" % (
            width[1] + delta) + "s" + "%" + "%d" % (
                width[2] + delta) + "s" + "%" + "%d" % (width[3] + delta) + "s"

        if self.history is None:
            self.update_history()

        self.print_list(
            self.history[::-1], format_str %
            (_("Date"), _("Description"), _("Amount"), _("Balance")))

    def update_history(self):
        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4) / 3
        format_str = "%" + "%d" % width[0] + "s" + "%" + "%d" % (
            width[1] + delta) + "s" + "%" + "%d" % (
                width[2] + delta) + "s" + "%" + "%d" % (width[3] + delta) + "s"

        b = 0
        self.history = []
        for item in self.wallet.get_history():
            tx_hash, height, conf, timestamp, value, balance = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp(
                        timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "------"
            else:
                time_str = 'unconfirmed'

            label = self.wallet.get_label(tx_hash)
            if len(label) > 40:
                label = label[0:37] + '...'
            self.history.append(
                format_str %
                (time_str, label, format_satoshis(value, whitespaces=True),
                 format_satoshis(balance, whitespaces=True)))

    def print_balance(self):
        if not self.network:
            msg = _("Offline")
        elif self.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else:
                c, u, x = self.wallet.get_balance()
                msg = _("Balance") + ": %f  " % (Decimal(c) / COIN)
                if u:
                    msg += "  [%f unconfirmed]" % (Decimal(u) / COIN)
                if x:
                    msg += "  [%f unmatured]" % (Decimal(x) / COIN)
        else:
            msg = _("Not connected")

        self.stdscr.addstr(self.maxy - 1, 3, msg)

        for i in range(self.num_tabs):
            self.stdscr.addstr(0,
                               2 + 2 * i + len(''.join(self.tab_names[0:i])),
                               ' ' + self.tab_names[i] + ' ',
                               curses.A_BOLD if self.tab == i else 0)

        self.stdscr.addstr(self.maxy - 1, self.maxx - 30,
                           ' '.join([_("Settings"),
                                     _("Network"),
                                     _("Quit")]))

    def print_receive(self):
        addr = self.wallet.get_unused_address()
        self.stdscr.addstr(2, 1, "Address: " + addr)
        self.print_qr(addr)

    def print_contacts(self):
        messages = map(lambda x: "%20s   %45s " % (x[0], x[1][1]),
                       self.contacts.items())
        self.print_list(messages, "%19s  %15s " % ("Key", "Value"))

    def print_addresses(self):
        fmt = "%-35s  %-30s"
        messages = map(
            lambda addr: fmt % (addr, self.wallet.labels.get(addr, "")),
            self.wallet.get_addresses())
        self.print_list(messages, fmt % ("Address", "Label"))

    def print_edit_line(self, y, label, text, index, size):
        text += " " * (size - len(text))
        self.stdscr.addstr(y, 2, label)
        self.stdscr.addstr(
            y, 15, text, curses.A_REVERSE if self.pos %
            6 == index else curses.color_pair(1))

    def print_send_tab(self):
        self.stdscr.clear()
        self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40)
        self.print_edit_line(5, _("Description"), self.str_description, 1, 40)
        self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15)
        self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15)
        self.stdscr.addstr(
            12, 15, _("[Send]"),
            curses.A_REVERSE if self.pos % 6 == 4 else curses.color_pair(2))
        self.stdscr.addstr(
            12, 25, _("[Clear]"),
            curses.A_REVERSE if self.pos % 6 == 5 else curses.color_pair(2))

    def print_banner(self):
        if self.network:
            self.print_list(self.network.banner.split('\n'))

    def print_qr(self, data):
        import qrcode, StringIO
        s = StringIO.StringIO()
        self.qr = qrcode.QRCode()
        self.qr.add_data(data)
        self.qr.print_ascii(out=s, invert=False)
        msg = s.getvalue()
        lines = msg.split('\n')
        for i, l in enumerate(lines):
            l = l.encode("utf-8")
            self.stdscr.addstr(i + 5, 5, l, curses.color_pair(3))

    def print_list(self, list, firstline=None):
        self.maxpos = len(list)
        if not self.maxpos: return
        if firstline:
            firstline += " " * (self.maxx - 2 - len(firstline))
            self.stdscr.addstr(1, 1, firstline)
        for i in range(self.maxy - 4):
            msg = list[i] if i < len(list) else ""
            msg += " " * (self.maxx - 2 - len(msg))
            m = msg[0:self.maxx - 2]
            m = m.encode(self.encoding)
            self.stdscr.addstr(
                i + 2, 1, m,
                curses.A_REVERSE if i == (self.pos % self.maxpos) else 0)

    def refresh(self):
        if self.tab == -1: return
        self.stdscr.border(0)
        self.print_balance()
        self.stdscr.refresh()

    def main_command(self):
        c = self.stdscr.getch()
        print c
        if c == curses.KEY_RIGHT: self.tab = (self.tab + 1) % self.num_tabs
        elif c == curses.KEY_LEFT: self.tab = (self.tab - 1) % self.num_tabs
        elif c == curses.KEY_DOWN: self.pos += 1
        elif c == curses.KEY_UP: self.pos -= 1
        elif c == 9: self.pos += 1  # tab
        elif curses.unctrl(c) in ['^W', '^C', '^X', '^Q']: self.tab = -1
        elif curses.unctrl(c) in ['^N']: self.network_dialog()
        elif curses.unctrl(c) == '^S': self.settings_dialog()
        else: return c
        if self.pos < 0: self.pos = 0
        if self.pos >= self.maxpos: self.pos = self.maxpos - 1

    def run_tab(self, i, print_func, exec_func):
        while self.tab == i:
            self.stdscr.clear()
            print_func()
            self.refresh()
            c = self.main_command()
            if c: exec_func(c)

    def run_history_tab(self, c):
        if c == 10:
            out = self.run_popup('', ["blah", "foo"])

    def edit_str(self, target, c, is_num=False):
        # detect backspace
        if c in [8, 127, 263] and target:
            target = target[:-1]
        elif not is_num or curses.unctrl(c) in '0123456789.':
            target += curses.unctrl(c)
        return target

    def run_send_tab(self, c):
        if self.pos % 6 == 0:
            self.str_recipient = self.edit_str(self.str_recipient, c)
        if self.pos % 6 == 1:
            self.str_description = self.edit_str(self.str_description, c)
        if self.pos % 6 == 2:
            self.str_amount = self.edit_str(self.str_amount, c, True)
        elif self.pos % 6 == 3:
            self.str_fee = self.edit_str(self.str_fee, c, True)
        elif self.pos % 6 == 4:
            if c == 10: self.do_send()
        elif self.pos % 6 == 5:
            if c == 10: self.do_clear()

    def run_receive_tab(self, c):
        if c == 10:
            out = self.run_popup('Address',
                                 ["Edit label", "Freeze", "Prioritize"])

    def run_contacts_tab(self, c):
        if c == 10 and self.contacts:
            out = self.run_popup(
                'Adress',
                ["Copy", "Pay to", "Edit label", "Delete"]).get('button')
            key = self.contacts.keys()[self.pos % len(self.contacts.keys())]
            if out == "Pay to":
                self.tab = 1
                self.str_recipient = key
                self.pos = 2
            elif out == "Edit label":
                s = self.get_string(6 + self.pos, 18)
                if s:
                    self.wallet.labels[address] = s

    def run_banner_tab(self, c):
        self.show_message(repr(c))
        pass

    def main(self):

        tty.setraw(sys.stdin)
        while self.tab != -1:
            self.run_tab(0, self.print_history, self.run_history_tab)
            self.run_tab(1, self.print_send_tab, self.run_send_tab)
            self.run_tab(2, self.print_receive, self.run_receive_tab)
            self.run_tab(3, self.print_addresses, self.run_banner_tab)
            self.run_tab(4, self.print_contacts, self.run_contacts_tab)
            self.run_tab(5, self.print_banner, self.run_banner_tab)

        tty.setcbreak(sys.stdin)
        curses.nocbreak()
        self.stdscr.keypad(0)
        curses.echo()
        curses.endwin()

    def do_clear(self):
        self.str_amount = ''
        self.str_recipient = ''
        self.str_fee = ''
        self.str_description = ''

    def do_send(self):
        if not is_valid(self.str_recipient):
            self.show_message(_('Invalid Cypherfunk address'))
            return
        try:
            amount = int(Decimal(self.str_amount) * COIN)
        except Exception:
            self.show_message(_('Invalid Amount'))
            return
        try:
            fee = int(Decimal(self.str_fee) * COIN)
        except Exception:
            self.show_message(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None
        try:
            tx = self.wallet.mktx([(TYPE_ADDRESS, self.str_recipient, amount)],
                                  password, self.config, fee)
        except Exception as e:
            self.show_message(str(e))
            return

        if self.str_description:
            self.wallet.labels[tx.hash()] = self.str_description

        self.show_message(_("Please wait..."), getchar=False)
        status, msg = self.network.broadcast(tx)

        if status:
            self.show_message(_('Payment sent.'))
            self.do_clear()
            #self.update_contacts_tab()
        else:
            self.show_message(_('Error'))

    def show_message(self, message, getchar=True):
        w = self.w
        w.clear()
        w.border(0)
        for i, line in enumerate(message.split('\n')):
            w.addstr(2 + i, 2, line)
        w.refresh()
        if getchar: c = self.stdscr.getch()

    def run_popup(self, title, items):
        return self.run_dialog(title,
                               map(lambda x: {
                                   'type': 'button',
                                   'label': x
                               }, items),
                               interval=1,
                               y_pos=self.pos + 3)

    def network_dialog(self):
        if not self.network:
            return
        params = self.network.get_parameters()
        host, port, protocol, proxy_config, auto_connect = params
        srv = 'auto-connect' if auto_connect else self.network.default_server
        out = self.run_dialog('Network', [
            {
                'label': 'server',
                'type': 'str',
                'value': srv
            },
            {
                'label': 'proxy',
                'type': 'str',
                'value': self.config.get('proxy', '')
            },
        ],
                              buttons=1)
        if out:
            if out.get('server'):
                server = out.get('server')
                auto_connect = server == 'auto-connect'
                if not auto_connect:
                    try:
                        host, port, protocol = server.split(':')
                    except Exception:
                        self.show_message("Error:" + server +
                                          "\nIn doubt, type \"auto-connect\"")
                        return False
                proxy = self.parse_proxy_options(
                    out.get('proxy')) if out.get('proxy') else None
                self.network.set_parameters(host, port, protocol, proxy,
                                            auto_connect)

    def settings_dialog(self):
        fee = str(Decimal(self.wallet.fee_per_kb(self.config)) / COIN)
        out = self.run_dialog('Settings', [{
            'label': 'Default fee',
            'type': 'satoshis',
            'value': fee
        }],
                              buttons=1)
        if out:
            if out.get('Default fee'):
                fee = int(Decimal(out['Default fee']) * COIN)
                self.config.set_key('fee_per_kb', fee, True)

    def password_dialog(self):
        out = self.run_dialog('Password', [{
            'label': 'Password',
            'type': 'password',
            'value': ''
        }],
                              buttons=1)
        return out.get('Password')

    def run_dialog(self, title, items, interval=2, buttons=None, y_pos=3):
        self.popup_pos = 0

        self.w = curses.newwin(
            5 + len(items) * interval + (2 if buttons else 0), 50, y_pos, 5)
        w = self.w
        out = {}
        while True:
            w.clear()
            w.border(0)
            w.addstr(0, 2, title)

            num = len(items)

            numpos = num
            if buttons: numpos += 2

            for i in range(num):
                item = items[i]
                label = item.get('label')
                if item.get('type') == 'list':
                    value = item.get('value', '')
                elif item.get('type') == 'satoshis':
                    value = item.get('value', '')
                elif item.get('type') == 'str':
                    value = item.get('value', '')
                elif item.get('type') == 'password':
                    value = '*' * len(item.get('value', ''))
                else:
                    value = ''
                if value is None:
                    value = ''
                if len(value) < 20:
                    value += ' ' * (20 - len(value))

                if item.has_key('value'):
                    w.addstr(2 + interval * i, 2, label)
                    w.addstr(
                        2 + interval * i, 15, value,
                        curses.A_REVERSE if self.popup_pos %
                        numpos == i else curses.color_pair(1))
                else:
                    w.addstr(
                        2 + interval * i, 2, label,
                        curses.A_REVERSE if self.popup_pos %
                        numpos == i else 0)

            if buttons:
                w.addstr(
                    5 + interval * i, 10, "[  ok  ]",
                    curses.A_REVERSE if self.popup_pos %
                    numpos == (numpos - 2) else curses.color_pair(2))
                w.addstr(
                    5 + interval * i, 25, "[cancel]",
                    curses.A_REVERSE if self.popup_pos %
                    numpos == (numpos - 1) else curses.color_pair(2))

            w.refresh()

            c = self.stdscr.getch()
            if c in [ord('q'), 27]: break
            elif c in [curses.KEY_LEFT, curses.KEY_UP]: self.popup_pos -= 1
            elif c in [curses.KEY_RIGHT, curses.KEY_DOWN]: self.popup_pos += 1
            else:
                i = self.popup_pos % numpos
                if buttons and c == 10:
                    if i == numpos - 2:
                        return out
                    elif i == numpos - 1:
                        return {}

                item = items[i]
                _type = item.get('type')

                if _type == 'str':
                    item['value'] = self.edit_str(item['value'], c)
                    out[item.get('label')] = item.get('value')

                elif _type == 'password':
                    item['value'] = self.edit_str(item['value'], c)
                    out[item.get('label')] = item['value']

                elif _type == 'satoshis':
                    item['value'] = self.edit_str(item['value'], c, True)
                    out[item.get('label')] = item.get('value')

                elif _type == 'list':
                    choices = item.get('choices')
                    try:
                        j = choices.index(item.get('value'))
                    except Exception:
                        j = 0
                    new_choice = choices[(j + 1) % len(choices)]
                    item['value'] = new_choice
                    out[item.get('label')] = item.get('value')

                elif _type == 'button':
                    out['button'] = item.get('label')
                    break

        return out
Exemplo n.º 6
0
class ElectrumGui:
    def __init__(self, config, network):

        self.config = config
        self.network = network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print "Wallet not found. try 'electrum create'"
            exit()

        self.wallet = Wallet(storage)
        self.wallet.start_threads(self.network)
        self.contacts = StoreDict(self.config, "contacts")

        locale.setlocale(locale.LC_ALL, "")
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None

        if self.network:
            self.network.register_callback("updated", self.update)
            self.network.register_callback("connected", self.refresh)
            self.network.register_callback("disconnected", self.refresh)
            self.network.register_callback("disconnecting", self.refresh)

        self.tab_names = [_("History"), _("Send"), _("Receive"), _("Contacts"), _("Wall")]
        self.num_tabs = len(self.tab_names)

    def set_cursor(self, x):
        try:
            curses.curs_set(x)
        except Exception:
            pass

    def restore_or_create(self):
        pass

    def verify_seed(self):
        pass

    def get_string(self, y, x):
        self.set_cursor(1)
        curses.echo()
        self.stdscr.addstr(y, x, " " * 20, curses.A_REVERSE)
        s = self.stdscr.getstr(y, x)
        curses.noecho()
        self.set_cursor(0)
        return s

    def update(self):
        self.update_history()
        if self.tab == 0:
            self.print_history()
        self.refresh()

    def print_history(self):

        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4) / 3
        format_str = (
            "%"
            + "%d" % width[0]
            + "s"
            + "%"
            + "%d" % (width[1] + delta)
            + "s"
            + "%"
            + "%d" % (width[2] + delta)
            + "s"
            + "%"
            + "%d" % (width[3] + delta)
            + "s"
        )

        if self.history is None:
            self.update_history()

        self.print_list(self.history[::-1], format_str % (_("Date"), _("Description"), _("Amount"), _("Balance")))

    def update_history(self):
        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4) / 3
        format_str = (
            "%"
            + "%d" % width[0]
            + "s"
            + "%"
            + "%d" % (width[1] + delta)
            + "s"
            + "%"
            + "%d" % (width[2] + delta)
            + "s"
            + "%"
            + "%d" % (width[3] + delta)
            + "s"
        )

        b = 0
        self.history = []

        for item in self.wallet.get_history():
            tx_hash, conf, value, timestamp, balance = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(" ")[:-3]
                except Exception:
                    time_str = "------"
            else:
                time_str = "pending"

            label, is_default_label = self.wallet.get_label(tx_hash)
            if len(label) > 40:
                label = label[0:37] + "..."
            self.history.append(
                format_str
                % (
                    time_str,
                    label,
                    format_satoshis(value, whitespaces=True),
                    format_satoshis(balance, whitespaces=True),
                )
            )

    def print_balance(self):
        if not self.network:
            msg = _("Offline")
        elif self.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else:
                c, u, x = self.wallet.get_balance()
                msg = _("Balance") + ": %f  " % (Decimal(c) / COIN)
                if u:
                    msg += "  [%f unconfirmed]" % (Decimal(u) / COIN)
                if x:
                    msg += "  [%f unmatured]" % (Decimal(x) / COIN)
        else:
            msg = _("Not connected")

        self.stdscr.addstr(self.maxy - 1, 3, msg)

        for i in range(self.num_tabs):
            self.stdscr.addstr(
                0,
                2 + 2 * i + len("".join(self.tab_names[0:i])),
                " " + self.tab_names[i] + " ",
                curses.A_BOLD if self.tab == i else 0,
            )

        self.stdscr.addstr(self.maxy - 1, self.maxx - 30, " ".join([_("Settings"), _("Network"), _("Quit")]))

    def print_contacts(self):
        messages = map(lambda x: "%20s   %45s " % (x[0], x[1][1]), self.contacts.items())
        self.print_list(messages, "%19s  %15s " % ("Key", "Value"))

    def print_receive(self):
        fmt = "%-35s  %-30s"
        messages = map(lambda addr: fmt % (addr, self.wallet.labels.get(addr, "")), self.wallet.addresses())
        self.print_list(messages, fmt % ("Address", "Label"))

    def print_edit_line(self, y, label, text, index, size):
        text += " " * (size - len(text))
        self.stdscr.addstr(y, 2, label)
        self.stdscr.addstr(y, 15, text, curses.A_REVERSE if self.pos % 6 == index else curses.color_pair(1))

    def print_send_tab(self):
        self.stdscr.clear()
        self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40)
        self.print_edit_line(5, _("Description"), self.str_description, 1, 40)
        self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15)
        self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15)
        self.stdscr.addstr(12, 15, _("[Send]"), curses.A_REVERSE if self.pos % 6 == 4 else curses.color_pair(2))
        self.stdscr.addstr(12, 25, _("[Clear]"), curses.A_REVERSE if self.pos % 6 == 5 else curses.color_pair(2))

    def print_banner(self):
        if self.network:
            self.print_list(self.network.banner.split("\n"))

    def print_list(self, list, firstline=None):
        self.maxpos = len(list)
        if not self.maxpos:
            return
        if firstline:
            firstline += " " * (self.maxx - 2 - len(firstline))
            self.stdscr.addstr(1, 1, firstline)
        for i in range(self.maxy - 4):
            msg = list[i] if i < len(list) else ""
            msg += " " * (self.maxx - 2 - len(msg))
            m = msg[0 : self.maxx - 2]
            m = m.encode(self.encoding)
            self.stdscr.addstr(i + 2, 1, m, curses.A_REVERSE if i == (self.pos % self.maxpos) else 0)

    def refresh(self):
        if self.tab == -1:
            return
        self.stdscr.border(0)
        self.print_balance()
        self.stdscr.refresh()

    def main_command(self):
        c = self.stdscr.getch()
        print c
        if c == curses.KEY_RIGHT:
            self.tab = (self.tab + 1) % self.num_tabs
        elif c == curses.KEY_LEFT:
            self.tab = (self.tab - 1) % self.num_tabs
        elif c == curses.KEY_DOWN:
            self.pos += 1
        elif c == curses.KEY_UP:
            self.pos -= 1
        elif c == 9:
            self.pos += 1  # tab
        elif curses.unctrl(c) in ["^W", "^C", "^X", "^Q"]:
            self.tab = -1
        elif curses.unctrl(c) in ["^N"]:
            self.network_dialog()
        elif curses.unctrl(c) == "^S":
            self.settings_dialog()
        else:
            return c
        if self.pos < 0:
            self.pos = 0
        if self.pos >= self.maxpos:
            self.pos = self.maxpos - 1

    def run_tab(self, i, print_func, exec_func):
        while self.tab == i:
            self.stdscr.clear()
            print_func()
            self.refresh()
            c = self.main_command()
            if c:
                exec_func(c)

    def run_history_tab(self, c):
        if c == 10:
            out = self.run_popup("", ["blah", "foo"])

    def edit_str(self, target, c, is_num=False):
        # detect backspace
        if c in [8, 127, 263] and target:
            target = target[:-1]
        elif not is_num or curses.unctrl(c) in "0123456789.":
            target += curses.unctrl(c)
        return target

    def run_send_tab(self, c):
        if self.pos % 6 == 0:
            self.str_recipient = self.edit_str(self.str_recipient, c)
        if self.pos % 6 == 1:
            self.str_description = self.edit_str(self.str_description, c)
        if self.pos % 6 == 2:
            self.str_amount = self.edit_str(self.str_amount, c, True)
        elif self.pos % 6 == 3:
            self.str_fee = self.edit_str(self.str_fee, c, True)
        elif self.pos % 6 == 4:
            if c == 10:
                self.do_send()
        elif self.pos % 6 == 5:
            if c == 10:
                self.do_clear()

    def run_receive_tab(self, c):
        if c == 10:
            out = self.run_popup("Address", ["Edit label", "Freeze", "Prioritize"])

    def run_contacts_tab(self, c):
        if c == 10 and self.contacts:
            out = self.run_popup("Adress", ["Copy", "Pay to", "Edit label", "Delete"]).get("button")
            key = self.contacts.keys()[self.pos % len(self.contacts.keys())]
            if out == "Pay to":
                self.tab = 1
                self.str_recipient = key
                self.pos = 2
            elif out == "Edit label":
                s = self.get_string(6 + self.pos, 18)
                if s:
                    self.wallet.labels[address] = s

    def run_banner_tab(self, c):
        self.show_message(repr(c))
        pass

    def main(self):

        tty.setraw(sys.stdin)
        while self.tab != -1:
            self.run_tab(0, self.print_history, self.run_history_tab)
            self.run_tab(1, self.print_send_tab, self.run_send_tab)
            self.run_tab(2, self.print_receive, self.run_receive_tab)
            self.run_tab(3, self.print_contacts, self.run_contacts_tab)
            self.run_tab(4, self.print_banner, self.run_banner_tab)

        tty.setcbreak(sys.stdin)
        curses.nocbreak()
        self.stdscr.keypad(0)
        curses.echo()
        curses.endwin()

    def do_clear(self):
        self.str_amount = ""
        self.str_recipient = ""
        self.str_fee = ""
        self.str_description = ""

    def do_send(self):
        if not is_valid(self.str_recipient):
            self.show_message(_("Invalid Bitcoin address"))
            return
        try:
            amount = int(Decimal(self.str_amount) * COIN)
        except Exception:
            self.show_message(_("Invalid Amount"))
            return
        try:
            fee = int(Decimal(self.str_fee) * COIN)
        except Exception:
            self.show_message(_("Invalid Fee"))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        try:
            tx = self.wallet.mktx([(self.str_recipient, amount)], password, self.config, fee)
        except Exception as e:
            self.show_message(str(e))
            return

        if self.str_description:
            self.wallet.labels[tx.hash()] = self.str_description

        h = self.wallet.send_tx(tx)
        self.show_message(_("Please wait..."), getchar=False)
        self.wallet.tx_event.wait()
        status, msg = self.wallet.receive_tx(h, tx)

        if status:
            self.show_message(_("Payment sent."))
            self.do_clear()
            # self.update_contacts_tab()
        else:
            self.show_message(_("Error"))

    def show_message(self, message, getchar=True):
        w = self.w
        w.clear()
        w.border(0)
        for i, line in enumerate(message.split("\n")):
            w.addstr(2 + i, 2, line)
        w.refresh()
        if getchar:
            c = self.stdscr.getch()

    def run_popup(self, title, items):
        return self.run_dialog(
            title, map(lambda x: {"type": "button", "label": x}, items), interval=1, y_pos=self.pos + 3
        )

    def network_dialog(self):
        if not self.network:
            return
        host, port, protocol, proxy_config, auto_connect = self.network.get_parameters()
        srv = "auto-connect" if auto_connect else self.network.default_server

        out = self.run_dialog(
            "Network",
            [
                {"label": "server", "type": "str", "value": srv},
                {"label": "proxy", "type": "str", "value": self.config.get("proxy", "")},
            ],
            buttons=1,
        )
        if out:
            if out.get("server"):
                server = out.get("server")
                auto_connect = server == "auto-connect"
                if not auto_connect:
                    try:
                        host, port, protocol = server.split(":")
                    except Exception:
                        self.show_message("Error:" + server + '\nIn doubt, type "auto-connect"')
                        return False

                if out.get("proxy"):
                    proxy = self.parse_proxy_options(out.get("proxy"))
                else:
                    proxy = None

                self.network.set_parameters(host, port, protocol, proxy, auto_connect)

    def settings_dialog(self):
        out = self.run_dialog(
            "Settings",
            [
                {
                    "label": "Default GUI",
                    "type": "list",
                    "choices": ["classic", "lite", "gtk", "text"],
                    "value": self.config.get("gui"),
                },
                {"label": "Default fee", "type": "satoshis", "value": format_satoshis(self.wallet.fee_per_kb).strip()},
            ],
            buttons=1,
        )
        if out:
            if out.get("Default GUI"):
                self.config.set_key("gui", out["Default GUI"], True)
            if out.get("Default fee"):
                fee = int(Decimal(out["Default fee"]) * COIN)
                self.config.set_key("fee_per_kb", fee, True)

    def password_dialog(self):
        out = self.run_dialog("Password", [{"label": "Password", "type": "password", "value": ""}], buttons=1)
        return out.get("Password")

    def run_dialog(self, title, items, interval=2, buttons=None, y_pos=3):
        self.popup_pos = 0

        self.w = curses.newwin(5 + len(items) * interval + (2 if buttons else 0), 50, y_pos, 5)
        w = self.w
        out = {}
        while True:
            w.clear()
            w.border(0)
            w.addstr(0, 2, title)

            num = len(items)

            numpos = num
            if buttons:
                numpos += 2

            for i in range(num):
                item = items[i]
                label = item.get("label")
                if item.get("type") == "list":
                    value = item.get("value", "")
                elif item.get("type") == "satoshis":
                    value = item.get("value", "")
                elif item.get("type") == "str":
                    value = item.get("value", "")
                elif item.get("type") == "password":
                    value = "*" * len(item.get("value", ""))
                else:
                    value = ""
                if value is None:
                    value = ""
                if len(value) < 20:
                    value += " " * (20 - len(value))

                if item.has_key("value"):
                    w.addstr(2 + interval * i, 2, label)
                    w.addstr(
                        2 + interval * i,
                        15,
                        value,
                        curses.A_REVERSE if self.popup_pos % numpos == i else curses.color_pair(1),
                    )
                else:
                    w.addstr(2 + interval * i, 2, label, curses.A_REVERSE if self.popup_pos % numpos == i else 0)

            if buttons:
                w.addstr(
                    5 + interval * i,
                    10,
                    "[  ok  ]",
                    curses.A_REVERSE if self.popup_pos % numpos == (numpos - 2) else curses.color_pair(2),
                )
                w.addstr(
                    5 + interval * i,
                    25,
                    "[cancel]",
                    curses.A_REVERSE if self.popup_pos % numpos == (numpos - 1) else curses.color_pair(2),
                )

            w.refresh()

            c = self.stdscr.getch()
            if c in [ord("q"), 27]:
                break
            elif c in [curses.KEY_LEFT, curses.KEY_UP]:
                self.popup_pos -= 1
            elif c in [curses.KEY_RIGHT, curses.KEY_DOWN]:
                self.popup_pos += 1
            else:
                i = self.popup_pos % numpos
                if buttons and c == 10:
                    if i == numpos - 2:
                        return out
                    elif i == numpos - 1:
                        return {}

                item = items[i]
                _type = item.get("type")

                if _type == "str":
                    item["value"] = self.edit_str(item["value"], c)
                    out[item.get("label")] = item.get("value")

                elif _type == "password":
                    item["value"] = self.edit_str(item["value"], c)
                    out[item.get("label")] = item["value"]

                elif _type == "satoshis":
                    item["value"] = self.edit_str(item["value"], c, True)
                    out[item.get("label")] = item.get("value")

                elif _type == "list":
                    choices = item.get("choices")
                    try:
                        j = choices.index(item.get("value"))
                    except Exception:
                        j = 0
                    new_choice = choices[(j + 1) % len(choices)]
                    item["value"] = new_choice
                    out[item.get("label")] = item.get("value")

                elif _type == "button":
                    out["button"] = item.get("label")
                    break

        return out
Exemplo n.º 7
0
class ElectrumGui:

    def __init__(self, config, network):

        self.config = config
        self.network = network
        storage = WalletStorage(config)
        if not storage.file_exists:
            print "Wallet not found. try 'electrum create'"
            exit()

        self.wallet = Wallet(storage)
        self.wallet.start_threads(self.network)

        locale.setlocale(locale.LC_ALL, '')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None
       
        if self.network: 
            self.network.register_callback('updated', self.update)
            self.network.register_callback('connected', self.refresh)
            self.network.register_callback('disconnected', self.refresh)
            self.network.register_callback('disconnecting', self.refresh)

        self.tab_names = [_("History"), _("Send"), _("Receive"), _("Contacts"), _("Wall")]
        self.num_tabs = len(self.tab_names)


    def set_cursor(self, x):
        try:
            curses.curs_set(x)
        except:
            pass

    def restore_or_create(self):
        pass

    def verify_seed(self):
        pass
    
    def get_string(self, y, x):
        self.set_cursor(1)
        curses.echo()
        self.stdscr.addstr( y, x, " "*20, curses.A_REVERSE)
        s = self.stdscr.getstr(y,x)
        curses.noecho()
        self.set_cursor(0)
        return s

    def update(self):
        self.update_history()
        if self.tab == 0: 
            self.print_history()
        self.refresh()

    def print_history(self):

        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        if self.history is None:
            self.update_history()

        self.print_list(self.history[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance")))

    def update_history(self):
        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        b = 0 
        self.history = []

        for item in self.wallet.get_tx_history():
            tx_hash, conf, is_mine, value, fee, balance, timestamp = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp( timestamp).isoformat(' ')[:-3]
                except:
                    time_str = "------"
            else:
                time_str = 'pending'

            label, is_default_label = self.wallet.get_label(tx_hash)
            self.history.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) )


    def print_balance(self):
        if not self.network:
            msg = _("Offline")
        elif self.network.interface and self.network.interface.is_connected:
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else: 
                c, u =  self.wallet.get_balance()
                msg = _("Balance")+": %f  "%(Decimal( c ) / 100000000)
                if u: msg += "  [%f unconfirmed]"%(Decimal( u ) / 100000000)
        else:
            msg = _("Not connected")
            
        self.stdscr.addstr( self.maxy -1, 3, msg)

        for i in range(self.num_tabs):
            self.stdscr.addstr( 0, 2 + 2*i + len(''.join(self.tab_names[0:i])), ' '+self.tab_names[i]+' ', curses.A_BOLD if self.tab == i else 0)
            
        self.stdscr.addstr( self.maxy -1, self.maxx-30, ' '.join([_("Settings"), _("Network"), _("Quit")]))


    def print_contacts(self):
        messages = map(lambda addr: "%30s    %30s       "%(addr, self.wallet.labels.get(addr,"")), self.wallet.addressbook)
        self.print_list(messages, "%19s  %25s "%("Address", "Label"))

    def print_receive(self):
        fmt = "%-35s  %-30s"
        messages = map(lambda addr: fmt % (addr, self.wallet.labels.get(addr,"")), self.wallet.addresses())
        self.print_list(messages,   fmt % ("Address", "Label"))

    def print_edit_line(self, y, label, text, index, size):
        text += " "*(size - len(text) )
        self.stdscr.addstr( y, 2, label)
        self.stdscr.addstr( y, 15, text, curses.A_REVERSE if self.pos%6==index else curses.color_pair(1))

    def print_send_tab(self):
        self.stdscr.clear()
        self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40)
        self.print_edit_line(5, _("Description"), self.str_description, 1, 40)
        self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15)
        self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15)
        self.stdscr.addstr( 12, 15, _("[Send]"), curses.A_REVERSE if self.pos%6==4 else curses.color_pair(2))
        self.stdscr.addstr( 12, 25, _("[Clear]"), curses.A_REVERSE if self.pos%6==5 else curses.color_pair(2))

    def print_banner(self):
        if self.network:
            self.print_list( self.network.banner.split('\n'))

    def print_list(self, list, firstline = None):
        self.maxpos = len(list)
        if not self.maxpos: return
        if firstline:
            firstline += " "*(self.maxx -2 - len(firstline))
            self.stdscr.addstr( 1, 1, firstline )
        for i in range(self.maxy-4):
            msg = list[i] if i < len(list) else ""
            msg += " "*(self.maxx - 2 - len(msg))
            m = msg[0:self.maxx - 2]
            m = m.encode(self.encoding)
            self.stdscr.addstr( i+2, 1, m, curses.A_REVERSE if i == (self.pos % self.maxpos) else 0)

    def refresh(self):
        if self.tab == -1: return
        self.stdscr.border(0)
        self.print_balance()
        self.stdscr.refresh()

    def main_command(self):
        c = self.stdscr.getch()
        print c
        if   c == curses.KEY_RIGHT: self.tab = (self.tab + 1)%self.num_tabs
        elif c == curses.KEY_LEFT: self.tab = (self.tab - 1)%self.num_tabs
        elif c == curses.KEY_DOWN: self.pos +=1
        elif c == curses.KEY_UP: self.pos -= 1
        elif c == 9: self.pos +=1 # tab
        elif curses.unctrl(c) in ['^W', '^C', '^X', '^Q']: self.tab = -1
        elif curses.unctrl(c) in ['^N']: self.network_dialog()
        elif curses.unctrl(c) == '^S': self.settings_dialog()
        else: return c
        if self.pos<0: self.pos=0
        if self.pos>=self.maxpos: self.pos=self.maxpos - 1

    def run_tab(self, i, print_func, exec_func):
        while self.tab == i:
            self.stdscr.clear()
            print_func()
            self.refresh()
            c = self.main_command()
            if c: exec_func(c)


    def run_history_tab(self, c):
        if c == 10:
            out = self.run_popup('',["blah","foo"])
            

    def edit_str(self, target, c, is_num=False):
        # detect backspace
        if c in [8, 127, 263] and target:
            target = target[:-1]
        elif not is_num or curses.unctrl(c) in '0123456789.':
            target += curses.unctrl(c)
        return target


    def run_send_tab(self, c):
        if self.pos%6 == 0:
            self.str_recipient = self.edit_str(self.str_recipient, c)
        if self.pos%6 == 1:
            self.str_description = self.edit_str(self.str_description, c)
        if self.pos%6 == 2:
            self.str_amount = self.edit_str(self.str_amount, c, True)
        elif self.pos%6 == 3:
            self.str_fee = self.edit_str(self.str_fee, c, True)
        elif self.pos%6==4:
            if c == 10: self.do_send()
        elif self.pos%6==5:
            if c == 10: self.do_clear()

            
    def run_receive_tab(self, c):
        if c == 10:
            out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"])
            
    def run_contacts_tab(self, c):
        if c == 10 and self.wallet.addressbook:
            out = self.run_popup('Adress', ["Copy", "Pay to", "Edit label", "Delete"]).get('button')
            address = self.wallet.addressbook[self.pos%len(self.wallet.addressbook)]
            if out == "Pay to":
                self.tab = 1
                self.str_recipient = address 
                self.pos = 2
            elif out == "Edit label":
                s = self.get_string(6 + self.pos, 18)
                if s:
                    self.wallet.labels[address] = s
            
    def run_banner_tab(self, c):
        self.show_message(repr(c))
        pass

    def main(self,url):

        tty.setraw(sys.stdin)
        while self.tab != -1:
            self.run_tab(0, self.print_history, self.run_history_tab)
            self.run_tab(1, self.print_send_tab, self.run_send_tab)
            self.run_tab(2, self.print_receive, self.run_receive_tab)
            self.run_tab(3, self.print_contacts, self.run_contacts_tab)
            self.run_tab(4, self.print_banner, self.run_banner_tab)

        tty.setcbreak(sys.stdin)
        curses.nocbreak()
        self.stdscr.keypad(0)
        curses.echo()
        curses.endwin()


    def do_clear(self):
        self.str_amount = ''
        self.str_recipient = ''
        self.str_fee = ''
        self.str_description = ''

    def do_send(self):
        if not is_valid(self.str_recipient):
            self.show_message(_('Invalid Bitcoin address'))
            return
        try:
            amount = int( Decimal( self.str_amount) * 100000000 )
        except:
            self.show_message(_('Invalid Amount'))
            return
        try:
            fee = int( Decimal( self.str_fee) * 100000000 )
        except:
            self.show_message(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        try:
            tx = self.wallet.mktx( [(self.str_recipient, amount)], password, fee)
        except BaseException, e:
            self.show_message(str(e))
            return
            
        if self.str_description: 
            self.wallet.labels[tx.hash()] = self.str_description

        h = self.wallet.send_tx(tx)
        self.show_message(_("Please wait..."), getchar=False)
        self.wallet.tx_event.wait()
        status, msg = self.wallet.receive_tx( h )

        if status:
            self.show_message(_('Payment sent.'))
            self.do_clear()
            #self.update_contacts_tab()
        else:
            self.show_message(_('Error'))
Exemplo n.º 8
0
class BitcoinWallet(Wallet):
    """
    This class is responsible for handling your wallet of bitcoins.
    """

    def __init__(self, wallet_dir, testnet=False):
        super(BitcoinWallet, self).__init__()

        if testnet:
            bitcoin.set_testnet()
            network.set_testnet()

        self.wallet_dir = wallet_dir
        self.wallet_file = 'tbtc_wallet' if testnet else 'btc_wallet'
        self.min_confirmations = 0
        self.created = False
        self.daemon = None
        keychain_pw = self.get_wallet_password()
        self.wallet_password = keychain_pw if keychain_pw else None  # Convert empty passwords to None
        self.storage = None
        self.wallet = None
        self.testnet = testnet
        self.load_wallet(self.wallet_dir, self.wallet_file)

    def load_wallet(self, wallet_dir, wallet_file):
        self.wallet_dir = wallet_dir
        self.wallet_file = wallet_file

        config = SimpleConfig(options={'cwd': self.wallet_dir, 'wallet_path': self.wallet_file})
        self.storage = WalletStorage(config.get_wallet_path())
        if self.storage.is_encrypted():
            self.storage.decrypt(self.wallet_password)

        if os.path.exists(config.get_wallet_path()):
            self.wallet = ElectrumWallet(self.storage)
            self.created = True
            self.start_daemon()
            self.open_wallet()

    def get_wallet_password(self):
        return keyring.get_password('tribler', 'btc_wallet_password')

    def set_wallet_password(self, password):
        keyring.set_password('tribler', 'btc_wallet_password', password)

    def get_daemon(self):
        """
        Return the daemon that can be used to send JSON RPC commands to. This method is here so we can unit test
        this class.
        """
        from electrum import daemon
        return daemon

    def start_daemon(self):
        options = {'verbose': False, 'cmd': 'daemon', 'testnet': self.testnet, 'oneserver': False, 'segwit': False,
                   'cwd': self.wallet_dir, 'portable': False, 'password': '',
                   'wallet_path': os.path.join('wallet', self.wallet_file)}
        if self.testnet:
            options['server'] = 'electrum.akinbo.org:51002:s'
        config = SimpleConfig(options)
        fd, _ = self.get_daemon().get_fd_or_server(config)

        if not fd:
            return

        self.daemon = self.get_daemon().Daemon(config, fd)
        self.daemon.start()

    def open_wallet(self):
        options = {'password': self.wallet_password, 'subcommand': 'load_wallet', 'verbose': False,
                   'cmd': 'daemon', 'testnet': self.testnet, 'oneserver': False, 'segwit': False,
                   'cwd': self.wallet_dir, 'portable': False, 'wallet_path': self.wallet_file}
        config = SimpleConfig(options)

        server = self.get_daemon().get_server(config)
        if server is not None:
            # Run the command to open the wallet
            server.daemon(options)

    def get_name(self):
        return 'Bitcoin' if not self.testnet else 'Testnet BTC'

    def get_identifier(self):
        return 'BTC'

    def create_wallet(self, password=''):
        """
        Create a new bitcoin wallet.
        """
        self._logger.info("Creating wallet in %s", self.wallet_dir)

        def run_on_thread(thread_method):
            # We are running code that writes to the wallet on a separate thread.
            # This is done because ethereum does not allow writing to a wallet from a daemon thread.
            wallet_thread = Thread(target=thread_method, name="ethereum-create-wallet")
            wallet_thread.setDaemon(False)
            wallet_thread.start()
            wallet_thread.join()

        seed = Mnemonic('en').make_seed()
        k = keystore.from_seed(seed, '')
        k.update_password(None, password)
        self.storage.put('keystore', k.dump())
        self.storage.put('wallet_type', 'standard')
        self.storage.set_password(password, bool(password))
        run_on_thread(self.storage.write)

        self.wallet = ElectrumWallet(self.storage)
        self.wallet.synchronize()
        run_on_thread(self.wallet.storage.write)
        self.created = True

        if password is not None:
            self.set_wallet_password(password)
        self.wallet_password = password

        self.start_daemon()
        self.open_wallet()

        self._logger.info("Bitcoin wallet saved in '%s'", self.wallet.storage.path)

        return succeed(None)

    def get_balance(self):
        """
        Return the balance of the wallet.
        """
        divider = 100000000
        if self.created:
            confirmed, unconfirmed, unmatured = self.wallet.get_balance()
            return succeed({
                "available": float(confirmed) / divider,
                "pending": float(unconfirmed + unmatured) / divider,
                "currency": 'BTC'
            })
        else:
            return succeed({"available": 0, "pending": 0, "currency": 'BTC'})

    def transfer(self, amount, address):
        def on_balance(balance):
            self._logger.info("Creating Bitcoin payment with amount %f to address %s", amount, address)
            if balance['available'] >= amount:
                options = {'tx_fee': '0.0005', 'password': self.wallet_password, 'verbose': False, 'nocheck': False,
                           'cmd': 'payto', 'wallet_path': self.wallet_file, 'destination': address,
                           'cwd': self.wallet_dir, 'testnet': self.testnet, 'rbf': False, 'amount': amount,
                           'segwit': False, 'unsigned': False, 'portable': False}
                config = SimpleConfig(options)

                server = self.get_daemon().get_server(config)
                result = server.run_cmdline(options)
                transaction_hex = result['hex']

                # Broadcast this transaction
                options = {'password': None, 'verbose': False, 'tx': transaction_hex, 'cmd': 'broadcast',
                           'testnet': self.testnet, 'timeout': 30, 'segwit': False, 'cwd': self.wallet_dir,
                           'portable': False}
                config = SimpleConfig(options)

                server = self.get_daemon().get_server(config)
                result = server.run_cmdline(options)

                if not result[0]:  # Transaction failed
                    return fail(RuntimeError(result[1]))

                return succeed(str(result[1]))
            else:
                return fail(InsufficientFunds())

        return self.get_balance().addCallback(on_balance)

    def monitor_transaction(self, txid):
        """
        Monitor a given transaction ID. Returns a Deferred that fires when the transaction is present.
        """
        monitor_deferred = Deferred()

        @inlineCallbacks
        def monitor_loop():
            transactions = yield self.get_transactions()
            for transaction in transactions:
                if transaction['id'] == txid:
                    self._logger.debug("Found transaction with id %s", txid)
                    monitor_deferred.callback(None)
                    monitor_lc.stop()

        self._logger.debug("Start polling for transaction %s", txid)
        monitor_lc = LoopingCall(monitor_loop)
        monitor_lc.start(1)

        return monitor_deferred

    def get_address(self):
        if not self.created:
            return ''
        return str(self.wallet.get_receiving_address())

    def get_transactions(self):
        options = {'nolnet': False, 'password': None, 'verbose': False, 'cmd': 'history',
                   'wallet_path': self.wallet_file, 'testnet': self.testnet, 'segwit': False, 'cwd': self.wallet_dir,
                   'portable': False}
        config = SimpleConfig(options)

        server = self.get_daemon().get_server(config)
        result = server.run_cmdline(options)

        transactions = []
        for transaction in result:
            outgoing = transaction['value'] < 0
            if outgoing:
                from_address = self.get_address()
                to_address = ''
            else:
                from_address = ''
                to_address = self.get_address()

            transactions.append({
                'id': transaction['txid'],
                'outgoing': outgoing,
                'from': from_address,
                'to': to_address,
                'amount': abs(transaction['value']),
                'fee_amount': 0.0,
                'currency': 'BTC',
                'timestamp': str(transaction['timestamp']),
                'description': ''
            })

        return succeed(transactions)

    def min_unit(self):
        return 0.0001  # This is the minimum amount of BTC we can transfer in this market
Exemplo n.º 9
0
class ElectrumGui:
    def __init__(self, config, network):
        self.network = network
        self.config = config
        storage = WalletStorage(config)
        if not storage.file_exists:
            print "Wallet not found. try 'electrum create'"
            exit()

        self.done = 0
        self.last_balance = ""

        set_verbosity(False)

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""

        self.wallet = Wallet(storage)
        self.wallet.start_threads(network)

        self.wallet.network.register_callback('updated', self.updated)
        self.wallet.network.register_callback('connected', self.connected)
        self.wallet.network.register_callback('disconnected',
                                              self.disconnected)
        self.wallet.network.register_callback('disconnecting',
                                              self.disconnecting)
        self.wallet.network.register_callback('peers', self.peers)
        self.wallet.network.register_callback('banner', self.print_banner)
        self.commands = [_("[h] - displays this help text"), \
                         _("[i] - display transaction history"), \
                         _("[o] - enter payment order"), \
                         _("[p] - print stored payment order"), \
                         _("[s] - send stored payment order"), \
                         _("[r] - show own receipt addresses"), \
                         _("[c] - display contacts"), \
                         _("[b] - print server banner"), \
                         _("[q] - quit") ]
        self.num_commands = len(self.commands)

    def main_command(self):
        self.print_balance()
        c = raw_input("enter command: ")
        if c == "h": self.print_commands()
        elif c == "i": self.print_history()
        elif c == "o": self.enter_order()
        elif c == "p": self.print_order()
        elif c == "s": self.send_order()
        elif c == "r": self.print_addresses()
        elif c == "c": self.print_contacts()
        elif c == "b": self.print_banner()
        elif c == "n": self.network_dialog()
        elif c == "e": self.settings_dialog()
        elif c == "q": self.done = 1
        else: self.print_commands()

    def peers(self):
        print("got peers list:")
        l = filter_protocol(self.wallet.network.get_servers(), 's')
        for s in l:
            print(s)

    def connected(self):
        print("connected")

    def disconnected(self):
        print("disconnected")

    def disconnecting(self):
        print("disconnecting")

    def updated(self):
        s = self.get_balance()
        if s != self.last_balance:
            print(s)
        self.last_balance = s
        return True

    def print_commands(self):
        self.print_list(self.commands, "Available commands")

    def print_history(self):
        width = [20, 40, 14, 14]
        delta = (80 - sum(width) - 4) / 3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%" \
        + "%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"
        b = 0
        messages = []

        for item in self.wallet.get_tx_history():
            tx_hash, confirmations, is_mine, value, fee, balance, timestamp = item
            if confirmations:
                try:
                    time_str = datetime.datetime.fromtimestamp(
                        timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "unknown"
            else:
                time_str = 'pending'

            label, is_default_label = self.wallet.get_label(tx_hash)
            messages.append(
                format_str %
                (time_str, label, format_satoshis(value, whitespaces=True),
                 format_satoshis(balance, whitespaces=True)))

        self.print_list(
            messages[::-1], format_str %
            (_("Date"), _("Description"), _("Amount"), _("Balance")))

    def print_balance(self):
        print(self.get_balance())

    def get_balance(self):
        if self.wallet.network.interface and self.wallet.network.interface.is_connected:
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else:
                c, u = self.wallet.get_balance()
                msg = _("Balance") + ": %f  " % (Decimal(c) / 100000000)
                if u: msg += "  [%f unconfirmed]" % (Decimal(u) / 100000000)
        else:
            msg = _("Not connected")

        return (msg)

    def print_contacts(self):
        messages = map(
            lambda addr: "%30s    %30s       " %
            (addr, self.wallet.labels.get(addr, "")), self.wallet.addressbook)
        self.print_list(messages, "%19s  %25s " % ("Address", "Label"))

    def print_addresses(self):
        messages = map(
            lambda addr: "%30s    %30s       " %
            (addr, self.wallet.labels.get(addr, "")), self.wallet.addresses())
        self.print_list(messages, "%19s  %25s " % ("Address", "Label"))

    def print_order(self):
        print("send order to " + self.str_recipient + ", amount: " + self.str_amount \
              + "\nfee: " + self.str_fee + ", desc: " + self.str_description)

    def enter_order(self):
        self.str_recipient = raw_input("Pay to: ")
        self.str_description = raw_input("Description : ")
        self.str_amount = raw_input("Amount: ")
        self.str_fee = raw_input("Fee: ")

    def send_order(self):
        self.do_send()

    def print_banner(self):
        for i, x in enumerate(self.wallet.network.banner.split('\n')):
            print(x)

    def print_list(self, list, firstline):
        self.maxpos = len(list)
        if not self.maxpos: return
        print(firstline)
        for i in range(self.maxpos):
            msg = list[i] if i < len(list) else ""
            print(msg)

    def main(self, url):
        while self.done == 0:
            self.main_command()

    def do_send(self):
        if not is_valid(self.str_recipient):
            print(_('Invalid Darkcoin address'))
            return
        try:
            amount = int(Decimal(self.str_amount) * 100000000)
        except Exception:
            print(_('Invalid Amount'))
            return
        try:
            fee = int(Decimal(self.str_fee) * 100000000)
        except Exception:
            print(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        c = ""
        while c != "y":
            c = raw_input("ok to send (y/n)?")
            if c == "n": return

        try:
            tx = self.wallet.mktx([(self.str_recipient, amount)], password,
                                  fee)
        except Exception as e:
            print(str(e))
            return

        if self.str_description:
            self.wallet.labels[tx.hash()] = self.str_description

        h = self.wallet.send_tx(tx)
        print(_("Please wait..."))
        self.wallet.tx_event.wait()
        status, msg = self.wallet.receive_tx(h, tx)

        if status:
            print(_('Payment sent.'))
            #self.do_clear()
            #self.update_contacts_tab()
        else:
            print(_('Error'))

    def network_dialog(self):
        print(
            "use 'electrum setconfig server/proxy' to change your network settings"
        )
        return True

    def settings_dialog(self):
        print("use 'electrum setconfig' to change your settings")
        return True

    def password_dialog(self):
        return getpass.getpass()

#   XXX unused

    def run_receive_tab(self, c):
        #if c == 10:
        #    out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"])
        return

    def run_contacts_tab(self, c):
        pass
Exemplo n.º 10
0
class ElectrumGui:

    def __init__(self, config, daemon, plugins):

        self.config = config
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists():
            print("Wallet not found. try 'electrum create'")
            exit()
        if storage.is_encrypted():
            password = getpass.getpass('Password:'******'')
        self.encoding = locale.getpreferredencoding()

        self.stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.start_color()
        curses.use_default_colors()
        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_CYAN)
        curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE)
        self.stdscr.keypad(1)
        self.stdscr.border(0)
        self.maxy, self.maxx = self.stdscr.getmaxyx()
        self.set_cursor(0)
        self.w = curses.newwin(10, 50, 5, 5)

        set_verbosity(False)
        self.tab = 0
        self.pos = 0
        self.popup_pos = 0

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""
        self.history = None

        if self.network:
            self.network.register_callback(self.update, ['updated'])

        self.tab_names = [_("History"), _("Send"), _("Receive"), _("Addresses"), _("Contacts"), _("Banner")]
        self.num_tabs = len(self.tab_names)


    def set_cursor(self, x):
        try:
            curses.curs_set(x)
        except Exception:
            pass

    def restore_or_create(self):
        pass

    def verify_seed(self):
        pass

    def get_string(self, y, x):
        self.set_cursor(1)
        curses.echo()
        self.stdscr.addstr( y, x, " "*20, curses.A_REVERSE)
        s = self.stdscr.getstr(y,x)
        curses.noecho()
        self.set_cursor(0)
        return s

    def update(self, event):
        self.update_history()
        if self.tab == 0:
            self.print_history()
        self.refresh()

    def print_history(self):

        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        if self.history is None:
            self.update_history()

        self.print_list(self.history[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance")))

    def update_history(self):
        width = [20, 40, 14, 14]
        delta = (self.maxx - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%"+"%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"

        b = 0
        self.history = []
        for item in self.wallet.get_history():
            tx_hash, height, conf, timestamp, value, balance = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "------"
            else:
                time_str = 'unconfirmed'

            label = self.wallet.get_label(tx_hash)
            if len(label) > 40:
                label = label[0:37] + '...'
            self.history.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) )


    def print_balance(self):
        if not self.network:
            msg = _("Offline")
        elif self.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _("Synchronizing...")
            else:
                c, u, x =  self.wallet.get_balance()
                msg = _("Balance")+": %f  "%(Decimal(c) / COIN)
                if u:
                    msg += "  [%f unconfirmed]"%(Decimal(u) / COIN)
                if x:
                    msg += "  [%f unmatured]"%(Decimal(x) / COIN)
        else:
            msg = _("Not connected")

        self.stdscr.addstr( self.maxy -1, 3, msg)

        for i in range(self.num_tabs):
            self.stdscr.addstr( 0, 2 + 2*i + len(''.join(self.tab_names[0:i])), ' '+self.tab_names[i]+' ', curses.A_BOLD if self.tab == i else 0)

        self.stdscr.addstr(self.maxy -1, self.maxx-30, ' '.join([_("Settings"), _("Network"), _("Quit")]))

    def print_receive(self):
        addr = self.wallet.get_receiving_address()
        self.stdscr.addstr(2, 1, "Address: "+addr)
        self.print_qr(addr)

    def print_contacts(self):
        messages = map(lambda x: "%20s   %45s "%(x[0], x[1][1]), self.contacts.items())
        self.print_list(messages, "%19s  %15s "%("Key", "Value"))

    def print_addresses(self):
        fmt = "%-35s  %-30s"
        messages = map(lambda addr: fmt % (addr, self.wallet.labels.get(addr,"")), self.wallet.get_addresses())
        self.print_list(messages,   fmt % ("Address", "Label"))

    def print_edit_line(self, y, label, text, index, size):
        text += " "*(size - len(text) )
        self.stdscr.addstr( y, 2, label)
        self.stdscr.addstr( y, 15, text, curses.A_REVERSE if self.pos%6==index else curses.color_pair(1))

    def print_send_tab(self):
        self.stdscr.clear()
        self.print_edit_line(3, _("Pay to"), self.str_recipient, 0, 40)
        self.print_edit_line(5, _("Description"), self.str_description, 1, 40)
        self.print_edit_line(7, _("Amount"), self.str_amount, 2, 15)
        self.print_edit_line(9, _("Fee"), self.str_fee, 3, 15)
        self.stdscr.addstr( 12, 15, _("[Send]"), curses.A_REVERSE if self.pos%6==4 else curses.color_pair(2))
        self.stdscr.addstr( 12, 25, _("[Clear]"), curses.A_REVERSE if self.pos%6==5 else curses.color_pair(2))
        self.maxpos = 6

    def print_banner(self):
        if self.network:
            self.print_list( self.network.banner.split('\n'))

    def print_qr(self, data):
        import qrcode
        try:
            from StringIO import StringIO
        except ImportError:
            from io import StringIO

        s = StringIO()
        self.qr = qrcode.QRCode()
        self.qr.add_data(data)
        self.qr.print_ascii(out=s, invert=False)
        msg = s.getvalue()
        lines = msg.split('\n')
        for i, l in enumerate(lines):
            l = l.encode("utf-8")
            self.stdscr.addstr(i+5, 5, l, curses.color_pair(3))

    def print_list(self, lst, firstline = None):
        lst = list(lst)
        self.maxpos = len(lst)
        if not self.maxpos: return
        if firstline:
            firstline += " "*(self.maxx -2 - len(firstline))
            self.stdscr.addstr( 1, 1, firstline )
        for i in range(self.maxy-4):
            msg = lst[i] if i < len(lst) else ""
            msg += " "*(self.maxx - 2 - len(msg))
            m = msg[0:self.maxx - 2]
            m = m.encode(self.encoding)
            self.stdscr.addstr( i+2, 1, m, curses.A_REVERSE if i == (self.pos % self.maxpos) else 0)

    def refresh(self):
        if self.tab == -1: return
        self.stdscr.border(0)
        self.print_balance()
        self.stdscr.refresh()

    def main_command(self):
        c = self.stdscr.getch()
        print(c)
        cc = curses.unctrl(c).decode()
        if   c == curses.KEY_RIGHT: self.tab = (self.tab + 1)%self.num_tabs
        elif c == curses.KEY_LEFT: self.tab = (self.tab - 1)%self.num_tabs
        elif c == curses.KEY_DOWN: self.pos +=1
        elif c == curses.KEY_UP: self.pos -= 1
        elif c == 9: self.pos +=1 # tab
        elif cc in ['^W', '^C', '^X', '^Q']: self.tab = -1
        elif cc in ['^N']: self.network_dialog()
        elif cc == '^S': self.settings_dialog()
        else: return c
        if self.pos<0: self.pos=0
        if self.pos>=self.maxpos: self.pos=self.maxpos - 1

    def run_tab(self, i, print_func, exec_func):
        while self.tab == i:
            self.stdscr.clear()
            print_func()
            self.refresh()
            c = self.main_command()
            if c: exec_func(c)


    def run_history_tab(self, c):
        if c == 10:
            out = self.run_popup('',["blah","foo"])


    def edit_str(self, target, c, is_num=False):
        # detect backspace
        cc = curses.unctrl(c).decode()
        if c in [8, 127, 263] and target:
            target = target[:-1]
        elif not is_num or cc in '0123456789.':
            target += cc
        return target


    def run_send_tab(self, c):
        if self.pos%6 == 0:
            self.str_recipient = self.edit_str(self.str_recipient, c)
        if self.pos%6 == 1:
            self.str_description = self.edit_str(self.str_description, c)
        if self.pos%6 == 2:
            self.str_amount = self.edit_str(self.str_amount, c, True)
        elif self.pos%6 == 3:
            self.str_fee = self.edit_str(self.str_fee, c, True)
        elif self.pos%6==4:
            if c == 10: self.do_send()
        elif self.pos%6==5:
            if c == 10: self.do_clear()


    def run_receive_tab(self, c):
        if c == 10:
            out = self.run_popup('Address', ["Edit label", "Freeze", "Prioritize"])

    def run_contacts_tab(self, c):
        if c == 10 and self.contacts:
            out = self.run_popup('Address', ["Copy", "Pay to", "Edit label", "Delete"]).get('button')
            key = list(self.contacts.keys())[self.pos%len(self.contacts.keys())]
            if out == "Pay to":
                self.tab = 1
                self.str_recipient = key
                self.pos = 2
            elif out == "Edit label":
                s = self.get_string(6 + self.pos, 18)
                if s:
                    self.wallet.labels[key] = s

    def run_banner_tab(self, c):
        self.show_message(repr(c))
        pass

    def main(self):

        tty.setraw(sys.stdin)
        while self.tab != -1:
            self.run_tab(0, self.print_history, self.run_history_tab)
            self.run_tab(1, self.print_send_tab, self.run_send_tab)
            self.run_tab(2, self.print_receive, self.run_receive_tab)
            self.run_tab(3, self.print_addresses, self.run_banner_tab)
            self.run_tab(4, self.print_contacts, self.run_contacts_tab)
            self.run_tab(5, self.print_banner, self.run_banner_tab)

        tty.setcbreak(sys.stdin)
        curses.nocbreak()
        self.stdscr.keypad(0)
        curses.echo()
        curses.endwin()


    def do_clear(self):
        self.str_amount = ''
        self.str_recipient = ''
        self.str_fee = ''
        self.str_description = ''

    def do_send(self):
Exemplo n.º 11
0
class ElectrumGui:

    def __init__(self, config, daemon, plugins):
        self.config = config
        self.network = daemon.network
        storage = WalletStorage(config.get_wallet_path())
        if not storage.file_exists:
            print("Wallet not found. try 'electrum create'")
            exit()
        if storage.is_encrypted():
            password = getpass.getpass('Password:'******'updated', 'banner'])
        self.commands = [_("[h] - displays this help text"), \
                         _("[i] - display transaction history"), \
                         _("[o] - enter payment order"), \
                         _("[p] - print stored payment order"), \
                         _("[s] - send stored payment order"), \
                         _("[r] - show own receipt addresses"), \
                         _("[c] - display contacts"), \
                         _("[b] - print server banner"), \
                         _("[q] - quit") ]
        self.num_commands = len(self.commands)

    def on_network(self, event, *args):
        if event == 'updated':
            self.updated()
        elif event == 'banner':
            self.print_banner()

    def main_command(self):
        self.print_balance()
        c = input("enter command: ")
        if c == "h" : self.print_commands()
        elif c == "i" : self.print_history()
        elif c == "o" : self.enter_order()
        elif c == "p" : self.print_order()
        elif c == "s" : self.send_order()
        elif c == "r" : self.print_addresses()
        elif c == "c" : self.print_contacts()
        elif c == "b" : self.print_banner()
        elif c == "n" : self.network_dialog()
        elif c == "e" : self.settings_dialog()
        elif c == "q" : self.done = 1
        else: self.print_commands()

    def updated(self):
        s = self.get_balance()
        if s != self.last_balance:
            print(s)
        self.last_balance = s
        return True

    def print_commands(self):
        self.print_list(self.commands, "Available commands")

    def print_history(self):
        width = [20, 40, 14, 14]
        delta = (80 - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%" \
        + "%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"
        messages = []

        for item in self.wallet.get_history():
            tx_hash, height, conf, timestamp, delta, balance = item
            if conf:
                try:
                    time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
                except Exception:
                    time_str = "unknown"
            else:
                time_str = 'unconfirmed'

            label = self.wallet.get_label(tx_hash)
            messages.append( format_str%( time_str, label, format_satoshis(delta, whitespaces=True), format_satoshis(balance, whitespaces=True) ) )

        self.print_list(messages[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance")))


    def print_balance(self):
        print(self.get_balance())

    def get_balance(self):
        if self.wallet.network.is_connected():
            if not self.wallet.up_to_date:
                msg = _( "Synchronizing..." )
            else:
                c, u, x =  self.wallet.get_balance()
                msg = _("Balance")+": %f  "%(Decimal(c) / COIN)
                if u:
                    msg += "  [%f unconfirmed]"%(Decimal(u) / COIN)
                if x:
                    msg += "  [%f unmatured]"%(Decimal(x) / COIN)
        else:
                msg = _( "Not connected" )

        return(msg)


    def print_contacts(self):
        messages = map(lambda x: "%20s   %45s "%(x[0], x[1][1]), self.contacts.items())
        self.print_list(messages, "%19s  %25s "%("Key", "Value"))

    def print_addresses(self):
        messages = map(lambda addr: "%30s    %30s       "%(addr, self.wallet.labels.get(addr,"")), self.wallet.get_addresses())
        self.print_list(messages, "%19s  %25s "%("Address", "Label"))

    def print_order(self):
        print("send order to " + self.str_recipient + ", amount: " + self.str_amount \
              + "\nfee: " + self.str_fee + ", desc: " + self.str_description)

    def enter_order(self):
        self.str_recipient = input("Pay to: ")
        self.str_description = input("Description : ")
        self.str_amount = input("Amount: ")
        self.str_fee = input("Fee: ")

    def send_order(self):
        self.do_send()

    def print_banner(self):
        for i, x in enumerate( self.wallet.network.banner.split('\n') ):
            print( x )

    def print_list(self, lst, firstline):
        lst = list(lst)
        self.maxpos = len(lst)
        if not self.maxpos: return
        print(firstline)
        for i in range(self.maxpos):
            msg = lst[i] if i < len(lst) else ""
            print(msg)


    def main(self):
        while self.done == 0: self.main_command()

    def do_send(self):
Exemplo n.º 12
0
class ElectrumGui:

    def __init__(self, config, network):
        self.network = network
        self.config = config
        storage = WalletStorage(config)
        if not storage.file_exists:
            print "Wallet not found. try 'electrum create'"
            exit()

	self.done = 0
        self.last_balance = ""

        set_verbosity(False)

        self.str_recipient = ""
        self.str_description = ""
        self.str_amount = ""
        self.str_fee = ""

        self.wallet = Wallet(storage)
        self.wallet.start_threads(network)
        
        self.wallet.network.register_callback('updated', self.updated)
        self.wallet.network.register_callback('connected', self.connected)
        self.wallet.network.register_callback('disconnected', self.disconnected)
        self.wallet.network.register_callback('disconnecting', self.disconnecting)
        self.wallet.network.register_callback('peers', self.peers)
        self.wallet.network.register_callback('banner', self.print_banner)
        self.commands = [_("[h] - displays this help text"), \
                         _("[i] - display transaction history"), \
                         _("[o] - enter payment order"), \
                         _("[p] - print stored payment order"), \
                         _("[s] - send stored payment order"), \
                         _("[r] - show own receipt addresses"), \
                         _("[c] - display contacts"), \
                         _("[b] - print server banner"), \
                         _("[q] - quit") ]
        self.num_commands = len(self.commands)

    def main_command(self):
        self.print_balance()
        c = raw_input("enter command: ")
        if   c == "h" : self.print_commands()
        elif c == "i" : self.print_history()
        elif c == "o" : self.enter_order()
        elif c == "p" : self.print_order()
        elif c == "s" : self.send_order()
        elif c == "r" : self.print_addresses()
        elif c == "c" : self.print_contacts()
        elif c == "b" : self.print_banner()
        elif c == "n" : self.network_dialog()
        elif c == "e" : self.settings_dialog()
        elif c == "q" : self.done = 1
        else: self.print_commands()

    def peers(self):
        print("got peers list:")
        l = filter_protocol(self.wallet.network.get_servers(), 's')
        for s in l:
            print (s)

    def connected(self):
        print ("connected")

    def disconnected(self):
        print ("disconnected")

    def disconnecting(self):
        print ("disconnecting")

    def updated(self):
        s = self.get_balance()
        if s != self.last_balance:
            print(s)
        self.last_balance = s
        return True

    def print_commands(self):
        self.print_list(self.commands, "Available commands")

    def print_history(self):
        width = [20, 40, 14, 14]
        delta = (80 - sum(width) - 4)/3
        format_str = "%"+"%d"%width[0]+"s"+"%"+"%d"%(width[1]+delta)+"s"+"%" \
        + "%d"%(width[2]+delta)+"s"+"%"+"%d"%(width[3]+delta)+"s"
        b = 0 
        messages = []

        for item in self.wallet.get_tx_history():
            tx_hash, confirmations, is_mine, value, fee, balance, timestamp = item
            if confirmations:
                try:
                    time_str = datetime.datetime.fromtimestamp( timestamp).isoformat(' ')[:-3]
                except:
                    time_str = "unknown"
            else:
                time_str = 'pending'

            label, is_default_label = self.wallet.get_label(tx_hash)
            messages.append( format_str%( time_str, label, format_satoshis(value, whitespaces=True), format_satoshis(balance, whitespaces=True) ) )

        self.print_list(messages[::-1], format_str%( _("Date"), _("Description"), _("Amount"), _("Balance")))


    def print_balance(self):
        print(self.get_balance())

    def get_balance(self):
        if self.wallet.network.interface and self.wallet.network.interface.is_connected:
            if not self.wallet.up_to_date:
                msg = _( "Synchronizing..." )
            else: 
                c, u =  self.wallet.get_balance()
                msg = _("Balance")+": %f  "%(Decimal( c ) / 100000000)
                if u: msg += "  [%f unconfirmed]"%(Decimal( u ) / 100000000)
        else:
                msg = _( "Not connected" )
            
        return(msg)


    def print_contacts(self):
        messages = map(lambda addr: "%30s    %30s       "%(addr, self.wallet.labels.get(addr,"")), self.wallet.addressbook)
        self.print_list(messages, "%19s  %25s "%("Address", "Label"))

    def print_addresses(self):
        messages = map(lambda addr: "%30s    %30s       "%(addr, self.wallet.labels.get(addr,"")), self.wallet.addresses())
        self.print_list(messages, "%19s  %25s "%("Address", "Label"))

    def print_order(self):
        print("send order to " + self.str_recipient + ", amount: " + self.str_amount \
              + "\nfee: " + self.str_fee + ", desc: " + self.str_description)

    def enter_order(self):
        self.str_recipient = raw_input("Pay to: ")
        self.str_description = raw_input("Description : ")
        self.str_amount = raw_input("Amount: ")
        self.str_fee = raw_input("Fee: ")

    def send_order(self):
        self.do_send()

    def print_banner(self):
        for i, x in enumerate( self.wallet.network.banner.split('\n') ):
            print( x )

    def print_list(self, list, firstline):
        self.maxpos = len(list)
        if not self.maxpos: return
        print(firstline)
        for i in range(self.maxpos):
            msg = list[i] if i < len(list) else ""
            print(msg)

           
    def main(self,url):
        while self.done == 0: self.main_command()

    def do_send(self):
        if not is_valid(self.str_recipient):
            print(_('Invalid Bitcoin address'))
            return
        try:
            amount = int( Decimal( self.str_amount) * 100000000 )
        except:
            print(_('Invalid Amount'))
            return
        try:
            fee = int( Decimal( self.str_fee) * 100000000 )
        except:
            print(_('Invalid Fee'))
            return

        if self.wallet.use_encryption:
            password = self.password_dialog()
            if not password:
                return
        else:
            password = None

        c = ""
        while c != "y":
            c = raw_input("ok to send (y/n)?")
            if c == "n": return

        try:
            tx = self.wallet.mktx( [(self.str_recipient, amount)], password, fee)
        except BaseException, e:
            print(str(e))
            return
            
        if self.str_description: 
            self.wallet.labels[tx.hash()] = self.str_description

        h = self.wallet.send_tx(tx)
        print(_("Please wait..."))
        self.wallet.tx_event.wait()
        status, msg = self.wallet.receive_tx( h )

        if status:
            print(_('Payment sent.'))
            #self.do_clear()
            #self.update_contacts_tab()
        else:
            print(_('Error'))