URI: 
       tElectrum for Android, first commit - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 5669e2887b7c719310f337071e35a468db78ca5b
   DIR parent 350a4629010b5c56852e457d38f1b04c71e4c11b
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Tue,  3 Apr 2012 17:32:08 +0200
       
       Electrum for Android, first commit
       
       Diffstat:
         A client/electrum4a.py                |     511 +++++++++++++++++++++++++++++++
       
       1 file changed, 511 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/client/electrum4a.py b/client/electrum4a.py
       t@@ -0,0 +1,511 @@
       +#!/usr/bin/env python
       +#
       +# Electrum - lightweight Bitcoin client
       +# Copyright (C) 2011 thomasv@gitorious
       +#
       +# This program is free software: you can redistribute it and/or modify
       +# it under the terms of the GNU General Public License as published by
       +# the Free Software Foundation, either version 3 of the License, or
       +# (at your option) any later version.
       +#
       +# This program is distributed in the hope that it will be useful,
       +# but WITHOUT ANY WARRANTY; without even the implied warranty of
       +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       +# GNU General Public License for more details.
       +#
       +# You should have received a copy of the GNU General Public License
       +# along with this program. If not, see <http://www.gnu.org/licenses/>.
       +
       +
       +
       +import android
       +from interface import WalletSynchronizer
       +from wallet import Wallet
       +from wallet import format_satoshis
       +from decimal import Decimal
       +
       +droid = android.Android()
       +wallet = Wallet()
       +wallet.set_path("/sdcard/electrum.dat")
       +wallet.read()
       +
       +
       +def get_history_layout(n):
       +    lines = wallet.get_tx_history()[-n:]
       +    rows = ""
       +    for line in lines:
       +        import datetime
       +        v = line['value'] 
       +        if line.has_key('timestamp'):
       +            dt = datetime.datetime.fromtimestamp( line['timestamp'] )
       +            if dt.date() == dt.today().date():
       +                time_str = str( dt.time() )
       +            else:
       +                time_str = str( dt.date() )
       +        else:
       +            time_str = 'pending'
       +
       +        label = line.get('label')
       +        if not label: label = line['tx_hash']
       +
       +        rows += """
       +    <TableRow>
       +        <TextView
       +            android:text="%s"
       +            android:padding="2px" />
       +        <TextView
       +            android:text="%s"
       +            android:padding="2px" />
       +        <TextView
       +            android:text="%s"
       +            android:gravity="right"
       +            android:padding="2px" />
       +    </TableRow>"""%(time_str, ' '+ label[0:10]+ '... ',  format_satoshis(v))
       +
       +
       +    output = """
       +<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
       +    android:layout_width="fill_parent"
       +    android:layout_height="wrap_content"
       +    android:stretchColumns="*">
       +    %s
       +</TableLayout>
       +"""% rows
       +    return output
       +
       +
       +
       +def show_addresses():
       +    droid.dialogCreateAlert("Addresses:")
       +    l = []
       +    for i in range(len(wallet.addresses)):
       +        addr = wallet.addresses[i]
       +        l.append( wallet.labels.get(addr,'') + ' ' + addr)
       +
       +    droid.dialogSetItems(l)
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse().result
       +    droid.dialogDismiss()
       +
       +    # show qr code
       +    print response
       +
       +
       +
       +main_layout = """<?xml version="1.0" encoding="utf-8"?>
       +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       +        android:id="@+id/background"
       +        android:orientation="vertical" android:layout_width="match_parent"
       +        android:layout_height="match_parent" android:background="#ff000000">
       +
       +        <TextView android:id="@+id/historyTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="History"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="center_vertical|center_horizontal|center">
       +        </TextView>
       +
       +        %s
       +
       +        <TextView android:id="@+id/balanceTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="TextView"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="center_vertical|center_horizontal|center">
       +        </TextView>
       +
       +        <LinearLayout android:layout_width="match_parent"
       +                android:layout_height="wrap_content" android:id="@+id/linearLayout1">
       +                <Button android:id="@+id/buttonSend" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Send"></Button>
       +                <Button android:id="@+id/buttonReceive" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Receive"></Button>
       +                <Button android:id="@+id/buttonQuit" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Quit"></Button>
       +        </LinearLayout>
       +
       +</LinearLayout>
       +"""%get_history_layout(10)
       +
       +
       +payto_layout="""<?xml version="1.0" encoding="utf-8"?>
       +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       +        android:id="@+id/background"
       +        android:orientation="vertical" 
       +        android:layout_width="match_parent"
       +        android:layout_height="match_parent" 
       +        android:background="#ff000000">
       +
       +        <TextView android:id="@+id/recipientTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Pay to:"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="left">
       +        </TextView>
       +
       +        <EditText android:id="@+id/recipient"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:tag="Tag Me" android:inputType="textCapWords|textPhonetic|number">
       +        </EditText>
       +
       +        <TextView android:id="@+id/labelTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Description:"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="left">
       +        </TextView>
       +
       +        <EditText android:id="@+id/label"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:tag="Tag Me" android:inputType="textCapWords|textPhonetic|number">
       +        </EditText>
       +
       +        <TextView android:id="@+id/amountLabelTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Amount:"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="left">
       +        </TextView>
       +
       +        <EditText android:id="@+id/amount"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:tag="Tag Me" android:inputType="textCapWords|number">
       +        </EditText>
       +
       +        <LinearLayout android:layout_width="match_parent"
       +                android:layout_height="wrap_content" android:id="@+id/linearLayout1">
       +                <Button android:id="@+id/buttonContacts" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Contacts"></Button>
       +                <Button android:id="@+id/buttonPay" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Send"></Button>
       +                <Button android:id="@+id/buttonCancelSend" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Cancel"></Button>
       +        </LinearLayout>
       +</LinearLayout>
       +"""
       +
       +
       +settings_layout = """<?xml version="1.0" encoding="utf-8"?>
       +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       +        android:id="@+id/background"
       +        android:orientation="vertical" 
       +        android:layout_width="match_parent"
       +        android:layout_height="match_parent" 
       +        android:background="#ff000000">
       +
       +        <TextView android:id="@+id/serverTextView" 
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:text="Server:"
       +                android:textAppearance="?android:attr/textAppearanceLarge" 
       +                android:gravity="left">
       +        </TextView>
       +
       +        <EditText android:id="@+id/server"
       +                android:layout_width="match_parent"
       +                android:layout_height="wrap_content" 
       +                android:tag="Tag Me" android:inputType="*">
       +        </EditText>
       +
       +        <LinearLayout android:layout_width="match_parent"
       +                android:layout_height="wrap_content" android:id="@+id/linearLayout1">
       +                <Button android:id="@+id/buttonServer" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Server List"></Button>
       +                <Button android:id="@+id/buttonSave" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Save"></Button>
       +                <Button android:id="@+id/buttonCancel" android:layout_width="wrap_content"
       +                        android:layout_height="wrap_content" android:text="Cancel"></Button>
       +        </LinearLayout>
       +
       +</LinearLayout>
       +"""
       +
       +
       +
       +droid.addOptionsMenuItem("Settings","settings",None,"")
       +droid.addOptionsMenuItem("Quit","quit",None,"")
       +
       +
       +def show_balance():
       +    c, u = wallet.get_balance()
       +    droid.fullSetProperty("balanceTextView","text","Balance:"+format_satoshis(c))
       +
       +
       +def recipient_dialog():
       +    title = 'Pay to:'
       +    message = ('Select recipient')
       +    droid.dialogCreateAlert(title, message)
       +    droid.dialogSetItems(wallet.addressbook)
       +    droid.dialogShow()
       +    response = droid.dialogGetResponse()
       +    result = response.result.get('item')
       +    droid.dialogDismiss()
       +    if result is not None:
       +        addr = wallet.addressbook[result]
       +        return addr
       +
       +
       +def pay_to(recipient, amount, fee, label):
       +
       +    if wallet.use_encryption:
       +        password  = droid.dialogGetPassword('Password').result
       +        print "password", password
       +    else:
       +        password = None
       +
       +    droid.dialogCreateSpinnerProgress("Electrum", "signing transaction...")
       +    droid.dialogShow()
       +    tx = wallet.mktx( recipient, amount, label, password, fee)
       +    print tx
       +    droid.dialogDismiss()
       +
       +    if tx:
       +        r, h = wallet.sendtx( tx )
       +        droid.dialogCreateAlert('tx sent', h)
       +        droid.dialogSetPositiveButtonText('OK')
       +        droid.dialogShow()
       +        response = droid.dialogGetResponse().result
       +        droid.dialogDismiss()
       +        return h
       +    else:
       +        return 'error'
       +
       +
       +
       +
       +
       +
       +
       +if not wallet.file_exists:
       +    droid.dialogCreateAlert("wallet file not found")
       +    droid.dialogSetPositiveButtonText('OK')
       +    droid.dialogShow()
       +    resp = droid.dialogGetResponse().result
       +    exit(1)
       +
       +
       +
       +
       +droid.dialogCreateSpinnerProgress("Electrum", "synchronizing")
       +droid.dialogShow()
       +WalletSynchronizer(wallet,True).start()
       +wallet.update()
       +wallet.save()
       +droid.dialogDismiss()
       +droid.vibrate()
       +
       +
       +
       +def main_loop():
       +
       +    droid.fullShow(main_layout)
       +    show_balance()
       +
       +    out = None
       +    while out is None:
       +
       +        event = droid.eventWait().result
       +        print "got event in main loop", event
       +
       +        if event["name"]=="click":
       +            id=event["data"]["id"]
       +            if id=="buttonQuit":
       +                out = 'exit'
       +
       +            elif id=="buttonSend":
       +                out = 'payto'
       +
       +            elif id=="buttonReceive":
       +                show_addresses()
       +
       +            elif id=="buttonQuit":
       +                out = 'quit'
       +
       +        elif event["name"]=="settings":
       +            out = 'settings'
       +
       +        elif event["name"]=="quit":
       +            out = 'quit'
       +
       +            #print droid.fullSetProperty("background","backgroundColor","0xff7f0000")
       +        #elif event["name"]=="screen":
       +        #    if event["data"]=="destroy":
       +        #        out = 'exit'
       +
       +    #droid.fullDismiss()
       +    return out
       +                    
       +def payto_loop():
       +    droid.fullShow(payto_layout)
       +    out = None
       +    while out is None:
       +        event = droid.eventWait().result
       +        print "got event in payto loop", event
       +
       +        if event["name"] == "click":
       +            id = event["data"]["id"]
       +
       +            if id=="buttonPay":
       +
       +                droid.fullQuery()
       +                recipient = droid.fullQueryDetail("recipient").result.get('text')
       +                label  = droid.fullQueryDetail("label").result.get('text')
       +                amount = droid.fullQueryDetail('amount').result.get('text')
       +                fee    = '0.001'
       +                amount = int( 100000000 * Decimal(amount) )
       +                fee    = int( 100000000 * Decimal(fee) )
       +                result = pay_to(recipient, amount, fee, label)
       +
       +                droid.dialogCreateAlert('result', result)
       +                droid.dialogSetPositiveButtonText('OK')
       +                droid.dialogShow()
       +                droid.dialogGetResponse()
       +                droid.dialogDismiss()
       +                out = 'main'
       +
       +                
       +            elif id=="buttonContacts":
       +                addr = recipient_dialog()
       +                droid.fullSetProperty("recipient","text",addr)
       +                
       +            elif id=="buttonCancelSend":
       +                out = 'main'
       +
       +        elif event["name"]=="settings":
       +            out = 'settings'
       +
       +        elif event["name"]=="quit":
       +            out = 'quit'
       +
       +        #elif event["name"]=="screen":
       +        #    if event["data"]=="destroy":
       +        #        out = 'main'
       +
       +    #droid.fullDismiss()
       +    return out
       +
       +
       +def history_loop():
       +    layout = get_history_layout()
       +    droid.fullShow(layout)
       +    out = None
       +    while out is None:
       +        event = droid.eventWait().result
       +        print "got event in history loop", event
       +        if event["name"] == "click":
       +
       +            if event["data"]["text"] == "OK":
       +                out = 'main'
       +
       +        elif event["name"] == "key":
       +            print repr(event["data"]["key"])
       +            if event["data"]["key"] == '4':
       +                out = 'main'
       +
       +        #elif event["name"]=="screen":
       +        #    if event["data"]=="destroy":
       +        #        out = 'main'
       +
       +    #droid.fullQuery()
       +    #print "Data entered =",droid.fullQueryDetail("editText1").result
       +    #droid.fullDismiss()
       +    return out
       +
       +def server_dialog(plist):
       +    droid.dialogCreateAlert("servers")
       +    droid.dialogSetItems( plist.keys() )
       +    droid.dialogShow()
       +    i = droid.dialogGetResponse().result.get('item')
       +    droid.dialogDismiss()
       +    if i is not None:
       +        response = plist.keys()[i]
       +        return response
       +
       +def protocol_dialog(plist):
       +    options=["TCP","HTTP","native"]
       +    droid.dialogCreateAlert("Protocol")
       +    droid.dialogSetSingleChoiceItems(options)
       +
       +
       +
       +def settings_loop():
       +    droid.fullShow(settings_layout)
       +    droid.fullSetProperty("server","text",wallet.server)
       +
       +    out = None
       +    while out is None:
       +        event = droid.eventWait().result
       +        if event["name"] == "click":
       +
       +            id = event["data"]["id"]
       +
       +            if id=="buttonServer":
       +                plist = {}
       +                for item in wallet.interface.servers:
       +                    host, pp = item
       +                    z = {}
       +                    for item2 in pp:
       +                        protocol, port = item2
       +                        z[protocol] = port
       +                    plist[host] = z
       +
       +                host = server_dialog(plist)
       +                p = plist[host]
       +                port = p['t']
       +                srv = host + ':' + port + ':t'
       +                droid.fullSetProperty("server","text",srv)
       +
       +            elif id=="buttonSave":
       +                droid.fullQuery()
       +                srv = droid.fullQueryDetail("server").result.get('text')
       +                try:
       +                    wallet.set_server(srv)
       +                    out = 'main'
       +                except:
       +                    droid.dialogCreateAlert('error')
       +                    droid.dialogSetPositiveButtonText('OK')
       +                    droid.dialogShow()
       +                    droid.dialogGetResponse()
       +                    droid.dialogDismiss()
       +                    
       +            elif id=="buttonCancel":
       +                out = 'main'
       +
       +        elif event["name"] == "key":
       +            print repr(event["data"]["key"])
       +            if event["data"]["key"] == '4':
       +                out = 'main'
       +
       +        elif event["name"]=="quit":
       +            out = 'quit'
       +
       +    return out
       +
       +                
       +
       +
       +s = 'main'
       +while True:
       +    if s == 'main':
       +        s = main_loop()
       +    elif s == 'payto':
       +        s = payto_loop()
       +    elif s == 'settings':
       +        s = settings_loop()
       +    elif s == 'history':
       +        s = history_loop()
       +    elif s == 'contacts':
       +        s = contacts_loop()
       +    else:
       +        break
       +
       +droid.fullDismiss()
       +droid.makeToast("Bye!")