You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
851 lines
25 KiB
851 lines
25 KiB
#!/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 |
|
import mnemonic |
|
|
|
import datetime |
|
|
|
|
|
|
|
def modal_dialog(title, msg = ''): |
|
droid.dialogCreateAlert(title,msg) |
|
droid.dialogSetPositiveButtonText('OK') |
|
droid.dialogShow() |
|
droid.dialogGetResponse() |
|
droid.dialogDismiss() |
|
|
|
def modal_question(q,msg): |
|
droid.dialogCreateAlert(q, msg) |
|
droid.dialogSetPositiveButtonText('OK') |
|
droid.dialogSetNegativeButtonText('Cancel') |
|
droid.dialogShow() |
|
response = droid.dialogGetResponse().result |
|
droid.dialogDismiss() |
|
return response.get('which') == 'positive' |
|
|
|
def select_from_contacts(): |
|
title = 'Contacts:' |
|
droid.dialogCreateAlert(title) |
|
droid.dialogSetPositiveButtonText('New contact') |
|
droid.dialogSetItems(wallet.addressbook) |
|
droid.dialogShow() |
|
response = droid.dialogGetResponse().result |
|
droid.dialogDismiss() |
|
|
|
if response.get('which') == 'positive': |
|
return 'newcontact' |
|
|
|
result = response.get('item') |
|
print result |
|
if result is not None: |
|
addr = wallet.addressbook[result] |
|
return addr |
|
|
|
|
|
def select_from_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 = response.result.get('item') |
|
droid.dialogDismiss() |
|
if result is not None: |
|
addr = wallet.addresses[result] |
|
return addr |
|
|
|
|
|
def protocol_dialog(host, z): |
|
droid.dialogCreateAlert('Protocol',host) |
|
protocols = z.keys() |
|
l = [] |
|
for p in protocols: |
|
if p == 't': l.append('TCP/stratum') |
|
if p == 'h': l.append('HTTP/Stratum') |
|
if p == 'n': l.append('TCP/native') |
|
droid.dialogSetSingleChoiceItems(l) |
|
droid.dialogSetPositiveButtonText('OK') |
|
droid.dialogSetNegativeButtonText('Cancel') |
|
droid.dialogShow() |
|
response = droid.dialogGetResponse().result |
|
if response.get('which') == 'positive': |
|
response = droid.dialogGetSelectedItems().result[0] |
|
droid.dialogDismiss() |
|
p = protocols[response] |
|
port = z[p] |
|
return host + ':' + port + ':' + p |
|
|
|
|
|
def qr_code_layout(addr): |
|
return """<html> |
|
<head> |
|
<title>QR code</title> |
|
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script> |
|
<script type="text/javascript" src="http://ecdsa.org/jquery.qrcode.min.js"></script> |
|
<script> |
|
var address = '%s'; |
|
var droid = new Android(); |
|
var cb = function() { |
|
droid.eventPost("main", ""); |
|
} |
|
</script> |
|
</head> |
|
|
|
<body> |
|
<div id="qrcode"></div> |
|
<div id="address"></div> |
|
<script> |
|
jQuery('#address').html("bitcoin:"+address); |
|
jQuery('#qrcode').qrcode("bitcoin:"+address); |
|
</script> |
|
|
|
<form onsubmit="cb(); return false;"> |
|
<input type="submit" value="Back" /> |
|
</form> |
|
</body> |
|
</html>"""%addr |
|
|
|
|
|
title = """ |
|
""" |
|
|
|
def make_layout(s, scrollable): |
|
content = """ |
|
<TextView android:id="@+id/titleTextView" |
|
android:layout_width="match_parent" |
|
android:layout_height="100" |
|
android:text="Electrum" |
|
android:textAppearance="?android:attr/textAppearanceLarge" |
|
android:gravity="center" |
|
android:textColor="0xff0055ff" |
|
android:textSize="30" > |
|
</TextView> |
|
|
|
%s """%s |
|
|
|
if scrollable: |
|
content = """ |
|
<ScrollView |
|
android:id="@+id/scrollview" |
|
android:layout_width="match_parent" |
|
android:layout_height="match_parent" > |
|
|
|
<LinearLayout |
|
android:orientation="vertical" |
|
android:layout_width="match_parent" |
|
android:layout_height="wrap_content" > |
|
|
|
%s |
|
|
|
</LinearLayout> |
|
</ScrollView> |
|
"""%content |
|
|
|
|
|
return """<?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="#ff000022"> |
|
|
|
%s |
|
</LinearLayout>"""%content |
|
|
|
|
|
|
|
|
|
def main_layout(): |
|
return make_layout(""" |
|
<TextView android:id="@+id/balanceTextView" |
|
android:layout_width="match_parent" |
|
android:layout_height="wrap_content" |
|
android:text="" |
|
android:textAppearance="?android:attr/textAppearanceLarge" |
|
android:gravity="left" |
|
android:textColor="0xffffffff" |
|
android:padding="10" |
|
android:textSize="18" > |
|
</TextView> |
|
|
|
|
|
<TextView android:id="@+id/historyTextView" |
|
android:layout_width="match_parent" |
|
android:layout_height="70" |
|
android:text="Recent transactions" |
|
android:textAppearance="?android:attr/textAppearanceLarge" |
|
android:gravity="center_vertical|center_horizontal|center"> |
|
</TextView> |
|
|
|
%s """%get_history_layout(15),True) |
|
|
|
|
|
|
|
payto_layout = make_layout(""" |
|
|
|
<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="text"> |
|
</EditText> |
|
|
|
<LinearLayout android:id="@+id/linearLayout1" |
|
android:layout_width="match_parent" |
|
android:layout_height="wrap_content"> |
|
<Button android:id="@+id/buttonQR" android:layout_width="wrap_content" |
|
android:layout_height="wrap_content" android:text="From QR code"></Button> |
|
<Button android:id="@+id/buttonContacts" android:layout_width="wrap_content" |
|
android:layout_height="wrap_content" android:text="From Contacts"></Button> |
|
</LinearLayout> |
|
|
|
|
|
<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="text"> |
|
</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="numberDecimal"> |
|
</EditText> |
|
|
|
<LinearLayout android:layout_width="match_parent" |
|
android:layout_height="wrap_content" android:id="@+id/linearLayout1"> |
|
<Button android:id="@+id/buttonPay" android:layout_width="wrap_content" |
|
android:layout_height="wrap_content" android:text="Send"></Button> |
|
</LinearLayout>""",False) |
|
|
|
|
|
|
|
settings_layout = make_layout(""" |
|
|
|
<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="text"> |
|
</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="Public servers"> |
|
</Button> |
|
<Button android:id="@+id/buttonProtocol" |
|
android:layout_width="wrap_content" |
|
android:layout_height="wrap_content" |
|
android:text="Protocol"> |
|
</Button> |
|
|
|
</LinearLayout> |
|
|
|
<TextView android:id="@+id/feeTextView" |
|
android:layout_width="match_parent" |
|
android:layout_height="wrap_content" |
|
android:text="Fee:" |
|
android:textAppearance="?android:attr/textAppearanceLarge" |
|
android:gravity="left"> |
|
</TextView> |
|
|
|
<EditText android:id="@+id/fee" |
|
android:layout_width="match_parent" |
|
android:layout_height="wrap_content" |
|
android:tag="Tag Me" |
|
android:inputType="numberDecimal"> |
|
</EditText> |
|
|
|
<Button android:id="@+id/buttonSave" android:layout_width="wrap_content" |
|
android:layout_height="wrap_content" android:text="Save"></Button> |
|
|
|
""",False) |
|
|
|
|
|
|
|
def get_history_values(n): |
|
values = [] |
|
h = wallet.get_tx_history() |
|
for i in range(n): |
|
line = h[-i-1] |
|
v = line['value'] |
|
try: |
|
dt = datetime.datetime.fromtimestamp( line['timestamp'] ) |
|
if dt.date() == dt.today().date(): |
|
time_str = str( dt.time() ) |
|
else: |
|
time_str = str( dt.date() ) |
|
conf = 'v' |
|
|
|
except: |
|
print line['timestamp'] |
|
time_str = 'pending' |
|
conf = 'o' |
|
|
|
tx_hash = line['tx_hash'] |
|
label = wallet.labels.get(tx_hash) |
|
is_default_label = (label == '') or (label is None) |
|
if is_default_label: label = line['default_label'] |
|
values.append((conf, ' ' + time_str, ' ' + format_satoshis(v,True), ' ' + label )) |
|
|
|
return values |
|
|
|
|
|
def get_history_layout(n): |
|
rows = "" |
|
i = 0 |
|
values = get_history_values(n) |
|
for v in values: |
|
a,b,c,d = v |
|
color = "0xff00ff00" if a == 'v' else "0xffff0000" |
|
rows += """ |
|
<TableRow> |
|
<TextView |
|
android:id="@+id/hl_%d_col1" |
|
android:layout_column="0" |
|
android:text="%s" |
|
android:textColor="%s" |
|
android:padding="3" /> |
|
<TextView |
|
android:id="@+id/hl_%d_col2" |
|
android:layout_column="1" |
|
android:text="%s" |
|
android:padding="3" /> |
|
<TextView |
|
android:id="@+id/hl_%d_col3" |
|
android:layout_column="2" |
|
android:text="%s" |
|
android:padding="3" /> |
|
<TextView |
|
android:id="@+id/hl_%d_col4" |
|
android:layout_column="3" |
|
android:text="%s" |
|
android:padding="4" /> |
|
</TableRow>"""%(i,a,color,i,b,i,c,i,d) |
|
i += 1 |
|
|
|
output = """ |
|
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|
android:layout_width="fill_parent" |
|
android:layout_height="wrap_content" |
|
android:stretchColumns="0,1,2,3"> |
|
%s |
|
</TableLayout>"""% rows |
|
return output |
|
|
|
def set_history_layout(n): |
|
values = get_history_values(n) |
|
i = 0 |
|
for v in values: |
|
a,b,c,d = v |
|
droid.fullSetProperty("hl_%d_col1"%i,"text", a) |
|
|
|
if a == 'v': |
|
droid.fullSetProperty("hl_%d_col1"%i, "textColor","0xff00ff00") |
|
else: |
|
droid.fullSetProperty("hl_%d_col1"%i, "textColor","0xffff0000") |
|
|
|
droid.fullSetProperty("hl_%d_col2"%i,"text", b) |
|
droid.fullSetProperty("hl_%d_col3"%i,"text", c) |
|
droid.fullSetProperty("hl_%d_col4"%i,"text", d) |
|
|
|
i += 1 |
|
|
|
|
|
|
|
def update_layout(): |
|
|
|
if not wallet.interface.is_connected: |
|
text = "Not connected..." |
|
elif wallet.blocks == 0: |
|
text = "Server not ready" |
|
elif not wallet.up_to_date: |
|
text = "Synchronizing..." |
|
else: |
|
c, u = wallet.get_balance() |
|
text = "Balance:"+format_satoshis(c) |
|
if u : text += ' [' + format_satoshis(u,True).strip() + ']' |
|
|
|
droid.fullSetProperty("balanceTextView", "text", text) |
|
|
|
if wallet.was_updated and wallet.up_to_date: |
|
global first_time_update |
|
if not first_time_update: |
|
droid.vibrate() |
|
else: |
|
first_time_update = False |
|
wallet.was_updated = False |
|
set_history_layout(15) |
|
|
|
|
|
|
|
|
|
def pay_to(recipient, amount, fee, label): |
|
|
|
if wallet.use_encryption: |
|
password = droid.dialogGetPassword('Password').result |
|
if not password: return |
|
else: |
|
password = None |
|
|
|
droid.dialogCreateSpinnerProgress("Electrum", "signing transaction...") |
|
droid.dialogShow() |
|
|
|
try: |
|
tx = wallet.mktx( recipient, amount, label, password, fee) |
|
except BaseException, e: |
|
modal_dialog('error', e.message) |
|
droid.dialogDismiss() |
|
return |
|
|
|
droid.dialogDismiss() |
|
|
|
r, h = wallet.sendtx( tx ) |
|
if r: |
|
modal_dialog('Payment sent', h) |
|
return True |
|
else: |
|
modal_dialog('Error', h) |
|
|
|
|
|
|
|
|
|
|
|
def recover(): |
|
if not modal_question("Wallet not found","restore from seed?"): |
|
exit(1) |
|
|
|
code = droid.scanBarcode() |
|
r = code.result |
|
if r: |
|
seed = r['extras']['SCAN_RESULT'] |
|
else: |
|
exit(1) |
|
|
|
if not modal_question('Seed', seed ): |
|
exit(1) |
|
|
|
wallet.seed = str(seed) |
|
wallet.init_mpk( wallet.seed ) |
|
|
|
change_password_dialog() |
|
|
|
droid.dialogCreateSpinnerProgress("Electrum", "recovering wallet...") |
|
droid.dialogShow() |
|
WalletSynchronizer(wallet,True).start() |
|
wallet.update() |
|
wallet.save() |
|
droid.dialogDismiss() |
|
droid.vibrate() |
|
|
|
if wallet.is_found(): |
|
# history and addressbook |
|
wallet.update_tx_history() |
|
wallet.fill_addressbook() |
|
modal_dialog("recovery successful") |
|
else: |
|
if not modal_question("no transactions found for this seed","do you want to keep this wallet?"): |
|
exit(1) |
|
wallet.save() |
|
|
|
|
|
|
|
def make_new_contact(): |
|
code = droid.scanBarcode() |
|
r = code.result |
|
if r: |
|
address = r['extras']['SCAN_RESULT'] |
|
if address: |
|
if wallet.is_valid(address): |
|
if modal_question('Add to contacts?', address): |
|
wallet.addressbook.append(address) |
|
wallet.save() |
|
else: |
|
modal_dialog('Invalid address', address) |
|
|
|
|
|
def main_loop(): |
|
update_layout() |
|
out = None |
|
while out is None: |
|
|
|
event = droid.eventWait(1000).result # wait for 1 second |
|
if not event: |
|
update_layout() |
|
continue |
|
|
|
print "got event in main loop", event |
|
|
|
if event["name"]=="click": |
|
id=event["data"]["id"] |
|
|
|
elif event["name"]=="settings": |
|
out = 'settings' |
|
|
|
elif event["name"]=="key": |
|
if event["data"]["key"] == '4': |
|
out = 'quit' |
|
|
|
elif event["name"] in menu_commands: |
|
out = event["name"] |
|
|
|
if out == 'contacts': |
|
global contact_addr |
|
contact_addr = select_from_contacts() |
|
if contact_addr == 'newcontact': |
|
make_new_contact() |
|
contact_addr = None |
|
if not contact_addr: |
|
out = None |
|
|
|
elif out == "receive": |
|
global receive_addr |
|
receive_addr = select_from_addresses() |
|
if not receive_addr: |
|
out = None |
|
|
|
|
|
return out |
|
|
|
|
|
def payto_loop(): |
|
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' |
|
try: |
|
amount = int( 100000000 * Decimal(amount) ) |
|
except: |
|
modal_dialog('Error','invalid amount') |
|
continue |
|
|
|
fee = int( 100000000 * Decimal(fee) ) |
|
result = pay_to(recipient, amount, fee, label) |
|
if result: |
|
out = 'main' |
|
|
|
elif id=="buttonContacts": |
|
addr = select_from_contacts() |
|
droid.fullSetProperty("recipient","text",addr) |
|
|
|
elif id=="buttonQR": |
|
code = droid.scanBarcode() |
|
r = code.result |
|
if r: |
|
addr = r['extras']['SCAN_RESULT'] |
|
if addr: |
|
droid.fullSetProperty("recipient","text",addr) |
|
|
|
elif event["name"] in menu_commands: |
|
out = event["name"] |
|
|
|
elif event["name"]=="key": |
|
if event["data"]["key"] == '4': |
|
out = 'main' |
|
|
|
#elif event["name"]=="screen": |
|
# if event["data"]=="destroy": |
|
# out = 'main' |
|
|
|
return out |
|
|
|
|
|
receive_addr = '' |
|
contact_addr = '' |
|
|
|
|
|
def receive_loop(): |
|
out = None |
|
while out is None: |
|
event = droid.eventWait().result |
|
print "got event", event |
|
out = 'main' |
|
return out |
|
|
|
def contacts_loop(): |
|
out = None |
|
while out is None: |
|
event = droid.eventWait().result |
|
print "got event", event |
|
out = 'main' |
|
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 seed_dialog(): |
|
if wallet.use_encryption: |
|
password = droid.dialogGetPassword('Password').result |
|
if not password: return |
|
else: |
|
password = None |
|
|
|
try: |
|
seed = wallet.pw_decode( wallet.seed, password) |
|
except: |
|
modal_dialog('error','incorrect password') |
|
return |
|
|
|
modal_dialog('Your seed is',seed) |
|
modal_dialog('Mnemonic code:', ' '.join(mnemonic.mn_encode(seed)) ) |
|
|
|
def change_password_dialog(): |
|
if wallet.use_encryption: |
|
password = droid.dialogGetPassword('Current password').result |
|
if not password: return |
|
else: |
|
password = None |
|
|
|
try: |
|
seed = wallet.pw_decode( wallet.seed, password) |
|
except: |
|
modal_dialog('error','incorrect password') |
|
return |
|
|
|
new_password = droid.dialogGetPassword('Choose a password').result |
|
password2 = droid.dialogGetPassword('Confirm new password').result |
|
if new_password != password2: |
|
modal_dialog('error','passwords do not match') |
|
return |
|
|
|
wallet.update_password(seed, new_password) |
|
if new_password: |
|
modal_dialog('Password updated','your wallet is encrypted') |
|
else: |
|
modal_dialog('Password removed','your wallet is not encrypted') |
|
|
|
|
|
def settings_loop(): |
|
droid.fullSetProperty("server","text",wallet.server) |
|
droid.fullSetProperty("fee","text", "%s"% str( Decimal( wallet.fee)/100000000 ) ) |
|
|
|
out = None |
|
while out is None: |
|
event = droid.eventWait().result |
|
print "got event", event |
|
|
|
plist = {} |
|
for item in wallet.interface.servers: |
|
host, pp = item |
|
z = {} |
|
for item2 in pp: |
|
protocol, port = item2 |
|
z[protocol] = port |
|
plist[host] = z |
|
|
|
|
|
if event["name"] == "click": |
|
id = event["data"]["id"] |
|
|
|
if id=="buttonServer": |
|
host = server_dialog(plist) |
|
if host: |
|
p = plist[host] |
|
port = p['t'] |
|
srv = host + ':' + port + ':t' |
|
droid.fullSetProperty("server","text",srv) |
|
|
|
elif id=="buttonProtocol": |
|
droid.fullQuery() |
|
srv = droid.fullQueryDetail("server").result.get('text') |
|
host = srv.split(':')[0] |
|
if host in plist: |
|
server = protocol_dialog(host, plist[host]) |
|
if server: |
|
droid.fullSetProperty("server","text",server) |
|
|
|
|
|
elif id=="buttonSave": |
|
droid.fullQuery() |
|
srv = droid.fullQueryDetail("server").result.get('text') |
|
fee = droid.fullQueryDetail("fee").result.get('text') |
|
try: |
|
wallet.set_server(srv) |
|
except: |
|
modal_dialog('error','invalid server') |
|
|
|
try: |
|
fee = int( 100000000 * Decimal(fee) ) |
|
if wallet.fee != fee: |
|
wallet.fee = fee |
|
wallet.save() |
|
except: |
|
modal_dialog('error','invalid fee value') |
|
|
|
elif event["name"] in menu_commands: |
|
out = event["name"] |
|
|
|
elif event["name"] == 'password': |
|
change_password_dialog() |
|
|
|
elif event["name"] == 'seed': |
|
seed_dialog() |
|
|
|
elif event["name"] == 'cancel': |
|
out = 'main' |
|
|
|
elif event["name"] == "key": |
|
if event["data"]["key"] == '4': |
|
out = 'main' |
|
|
|
return out |
|
|
|
|
|
|
|
menu_commands = ["send", "receive", "settings", "contacts", "main"] |
|
|
|
|
|
first_time_update = True |
|
droid = android.Android() |
|
wallet = Wallet() |
|
|
|
wallet.set_path("/sdcard/electrum.dat") |
|
wallet.read() |
|
if not wallet.file_exists: |
|
recover() |
|
else: |
|
WalletSynchronizer(wallet,True).start() |
|
|
|
|
|
s = 'main' |
|
|
|
def add_menu(s): |
|
droid.clearOptionsMenu() |
|
if s == 'main': |
|
droid.addOptionsMenuItem("Send","send",None,"") |
|
droid.addOptionsMenuItem("Receive","receive",None,"") |
|
droid.addOptionsMenuItem("Contacts","contacts",None,"") |
|
droid.addOptionsMenuItem("Settings","settings",None,"") |
|
elif s == 'receive': |
|
droid.addOptionsMenuItem("Back","main",None,"") |
|
elif s == 'contacts': |
|
droid.addOptionsMenuItem("Back","main",None,"") |
|
#droid.addOptionsMenuItem("Pay to","paytocontact",None,"") |
|
#droid.addOptionsMenuItem("Edit label","editcontact",None,"") |
|
#droid.addOptionsMenuItem("Delete","removecontact",None,"") |
|
elif s == 'settings': |
|
droid.addOptionsMenuItem("Password","password",None,"") |
|
droid.addOptionsMenuItem("Seed","seed",None,"") |
|
|
|
|
|
|
|
|
|
|
|
while True: |
|
add_menu(s) |
|
if s == 'main': |
|
droid.fullShow(main_layout()) |
|
s = main_loop() |
|
droid.fullDismiss() |
|
|
|
elif s == 'send': |
|
droid.fullShow(payto_layout) |
|
s = payto_loop() |
|
droid.fullDismiss() |
|
|
|
elif s == 'receive': |
|
f = open('/sdcard/sl4a/scripts/recv.html',"w") |
|
f.write(qr_code_layout(receive_addr)) |
|
f.close() |
|
wvs = droid.webViewShow("file:///sdcard/sl4a/scripts/recv.html") |
|
s = receive_loop() |
|
|
|
elif s == 'contacts': |
|
f = open('/sdcard/sl4a/scripts/recv.html',"w") |
|
f.write(qr_code_layout(contact_addr)) |
|
f.close() |
|
droid.webViewShow("file:///sdcard/sl4a/scripts/recv.html") |
|
s = contacts_loop() |
|
|
|
elif s == 'settings': |
|
droid.fullShow(settings_layout) |
|
s = settings_loop() |
|
droid.fullDismiss() |
|
else: |
|
break |
|
|
|
droid.makeToast("Bye!")
|
|
|