Initial commit for Kivy GUI wallet

This commit is contained in:
jwinterm
2014-05-25 16:02:48 -05:00
commit 8068fc74a9
10 changed files with 471 additions and 0 deletions
View File
View File
+15
View File
@@ -0,0 +1,15 @@
import os
import subprocess
def bitmonerodloader():
"""Start bitmonerod and/or simplewallet and collect wallet name and address"""
#Start bitmonerod daemon if not running
if os.name == 'nt':
daemonproc = subprocess.Popen("start bitmonerod --rpc-bind-port 18081",
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
elif os.name == 'posix':
daemonproc = subprocess.Popen(['./bitmonerod --rpc-bind-port 18081'],
creationflags=subprocess.CREATE_NEW_CONSOLE,
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
+38
View File
@@ -0,0 +1,38 @@
import requests
import json
serverURL = 'http://localhost:8082/json_rpc'
def checkbalancerpccall():
"""function to make rpc call to simplewallet to get current balance"""
payload = json.dumps({
"jsonrpc": "2.0",
"method": "getbalance",
"params": {}
})
print 'attempting rpc call'
try:
#Make rpc call
headers = {'content-type': 'application/json'}
resp = requests.get(serverURL, headers=headers, data=payload)
output = json.loads(resp.text)
#Parse json data to get balance info
rawbalance = str(output[u'result'][u'balance']/1e12)
rawunlockedbalance = str(output[u'result'][u'unlocked_balance']/1e12)
#Format data for kivy
balance = '[color=00ff00]'+rawbalance+'[/color]'
unlockedbalance = '[color=00ff00]'+rawunlockedbalance+'[/color]'
return balance, unlockedbalance
except:
#Return out of sync if bitmonerod is not ready
return '[color=ff0000]out of sync[/color]', '[color=ff0000]out of sync[/color]'
if __name__ == "__main__":
checkbalance()
+42
View File
@@ -0,0 +1,42 @@
import requests
import json
import time
serverURL = 'http://localhost:8081/json_rpc'
headers = {'content-type': 'application/json'}
payload = json.dumps({
"jsonrpc": "2.0",
"id": "test",
"method": "getlastblockheader"
})
def checklastblockrpccall():
synced = False
while synced == False:
resp = requests.get(serverURL, headers=headers, data=payload)
output = json.loads(resp.text)
try:
output[u'result'][u'status'] == 'OK'
synced = True
except:
time.sleep(2)
print "Waiting for bitmonerod client to sync with network..."
try:
if output[u'error'][u'message'] == 'Core is busy':
time.sleep(3)
except:
print '2nd'
print "Client is synced with the network."
print output
time.sleep(4)
return output
if __name__ == "__main__":
checklastblockrpccall()
+22
View File
@@ -0,0 +1,22 @@
import requests
import json
serverURL = 'http://localhost:8082/json_rpc'
payload = json.dumps({
"jsonrpc": "2.0",
"method": "store",
"params": {}
})
def checkwalletrpccall():
headers = {'content-type': 'application/json'}
resp = requests.get(serverURL, headers=headers, data=payload)
output = json.loads(resp.text)
print output
# return output[u'result'][u'balance'], output[u'result'][u'unlocked_balance']
if __name__ == "__main__":
checkwallet()
+43
View File
@@ -0,0 +1,43 @@
import os
import time
import subprocess
import checklastblock
def simplewalletloader(walletname, walletpw, queue):
"""Function to create and/or open wallet in simplewallet rpc mode"""
#Generate wallet if file doesn't exist in local directory
if not os.path.isfile('./'+walletname):
print "Generating wallet file " + walletname
if os.name == 'nt':
walletgen = subprocess.Popen(
"simplewallet --generate-new-wallet " + walletname + " --password " + walletpw,
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
elif os.name == 'posix':
walletgen = subprocess.Popen(
"./simplewallet --generate-new-wallet " + walletname + " --password " + walletpw,
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
creationflags=subprocess.CREATE_NEW_CONSOLE)
time.sleep(7)
walletgen.terminate()
#Launch simplewallet in rpc mode
print "***Opening ___" + walletname + "___ wallet file rpc interface***"
if os.name == 'nt':
walletproc = subprocess.Popen("start simplewallet --wallet {0} --password {1} --rpc-bind-port 8082".format(walletname, walletpw),
shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
elif os.name == 'posix':
walletproc = subprocess.Popen(["./simplewallet --wallet {0} --password {1} --rpc-bind-port 8082".format(
walletname, walletpw)], creationflags=subprocess.CREATE_NEW_CONSOLE)
#Read address file to get address
with open(walletname + ".address.txt", "r") as addressfile:
rawaddress = addressfile.read().replace('\n', '')
#Format data for display in kivy
walletname = walletname + ' wallet file has been opened'
address = '[color=00ffff][ref=addressselection]' + rawaddress + '[/ref][/color]'
queue.put((walletname, address, rawaddress))
+42
View File
@@ -0,0 +1,42 @@
import requests
import json
from ctypes import c_uint64
serverURL = 'http://localhost:8082/json_rpc'
def transferfundsrpccall(amount, address, mixin):
"""function to transfer funds to a single address"""
atomicamount = c_uint64(int((float(amount)*1e12)-1e6))
address = str(address)
mixin = int(mixin)
mro_fee = c_uint64(int(1e6))
payload = json.dumps({
"jsonrpc":"2.0",
"method":"transfer",
"params":{
"destinations":[
{
"amount":atomicamount.value,
"address":address
}
],
"fee":mro_fee.value,
"mixin":mixin,
"unlock_time":0
}
})
print payload
try:
headers = {'content-type': 'application/json'}
resp = requests.get(serverURL, headers=headers, data=payload)
output = json.loads(resp.text)
print output
except:
print "transfer error :0 !!!"
if __name__ == "__main__":
checkbalance()
+189
View File
@@ -0,0 +1,189 @@
#:kivy 1.8.0
<RootWidget>:
cols: 1
input_name: name_input
input_pw: pw_input
label_myaddress: myaddress_label
label_balance: balance_label
label_unlockedbalance: unlockedbalance_label
input_address: address_input
input_amount: amount_input
input_mixin: mixin_input
input_paymentid: paymentid_input
BoxLayout:
size_hint_y: 0.4
Label:
text: "[b]Kivy Monero/Cryptonote GUI RPC Wallet[/b]"
markup: True
font_size: 20
BoxLayout:
size_hint_y: 0.1
BoxLayout:
size_hint_y: 0.35
Label:
Button:
size_hint_x: 1.7
text: "Launch bitmonerod daemon"
on_press: root.launchdaemon()
Label:
Button:
size_hint_x: 1.7
text: "Launch simplewallet daemon"
on_press: root.launchwallet()
Label:
BoxLayout:
size_hint_y: 0.2
BoxLayout:
padding: 10,0,40,0
size_hint_y: 0.3
Label:
text: "Wallet name: "
size_hint_x: 0.2
font_size: 16
TextInput:
id: name_input
size_hint_x: 0.8
font_size: 12
text: root.walletname
BoxLayout:
padding: 10,0,40,0
size_hint_y: 0.3
Label:
text: "Wallet password: "
size_hint_x: 0.2
font_size: 16
TextInput:
id: pw_input
size_hint_x: 0.8
font_size: 12
text: root.walletpw
password: True
BoxLayout:
size_hint_y: 0.5
padding: 10,0,80,0
Label:
text: "Wallet address: \n [size=10](click address to copy)[/size]"
markup: True
size_hint_x: 0.3
font_size: 16
halign: 'center'
Label:
id: myaddress_label
text: "[ref=addressselection]uninitialized[/ref]"
markup: True
size_hint_x: 0.7
font_size: 10
on_ref_press: root.selectaddress()
BoxLayout:
size_hint_y: 0.3
Label:
text: "Balance: "
size_hint_x: 0.3
font_size: 16
Label:
id: balance_label
text: root.balance
size_hint_x: 0.7
markup: True
font_size: 16
BoxLayout:
size_hint_y: 0.3
Label:
text: "Unlocked balance: "
size_hint_x: 0.3
font_size: 16
Label:
id: unlockedbalance_label
text: root.unlockedbalance
size_hint_x: 0.7
markup: True
font_size: 16
BoxLayout:
size_hint_y: 0.35
Label:
Button:
text: "Refresh balance"
on_press: root.checkbalance()
font_size: 20
Label:
BoxLayout:
size_hint_y: 0.2
BoxLayout:
padding: 10,0,40,0
size_hint_y: 0.3
Label:
text: "Send to address:"
size_hint_x: 0.2
TextInput:
id: address_input
size_hint_x: 0.8
font_size: 10
multiline: False
BoxLayout:
padding: 10,0,40,0
size_hint_y: 0.3
Label:
text: "Amount MRO:"
size_hint_x: 0.2
TextInput:
id: amount_input
size_hint_x: 0.8
font_size: 10
multiline: False
BoxLayout:
padding: 10,0,40,0
size_hint_y: 0.3
Label:
text: "Mixin amount:"
size_hint_x: 0.2
TextInput:
id: mixin_input
size_hint_x: 0.8
font_size: 10
multiline: False
BoxLayout:
padding: 10,0,40,0
size_hint_y: 0.3
Label:
text: "Payment ID:"
size_hint_x: 0.2
TextInput:
id: paymentid_input
size_hint_x: 0.8
font_size: 10
text: "DISABLED!!! Do not send funds to exchanges. Disabled payment id field is required for depositing on exchanges!"
multiline: False
BoxLayout:
padding: 200,0,200,0
size_hint_y: 0.35
Button:
text: "Transfer funds"
on_press: root.transferfunds()
font_size: 20
BoxLayout:
size_hint_y: 0.1
+80
View File
@@ -0,0 +1,80 @@
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.properties import ObjectProperty
from kivy.core.clipboard import Clipboard
from functions.bitmonerodloader import bitmonerodloader
from functions.checkbalance import checkbalancerpccall
from functions.transferfunds import transferfundsrpccall
from functions.simplewalletloader import simplewalletloader
from sys import argv
from multiprocessing import Process, Queue
class RootWidget(GridLayout):
"""Root Kivy widget class"""
#Ininitalize variables
if len(argv) == 1:
walletname, walletpw = "", ""
elif len(argv) == 3:
walletname, walletpw = argv[1], argv[2]
address, rawaddress = "uninitialized", "uninitialized"
balance, unlockedbalance = "uninitialized", "uninitialized"
#Setup object properties to be modified/used
input_name = ObjectProperty()
input_pw = ObjectProperty()
label_myaddress = ObjectProperty()
label_balance = ObjectProperty()
label_unlockedbalance = ObjectProperty()
input_address = ObjectProperty()
input_amount = ObjectProperty()
input_mixin = ObjectProperty()
walletqueue = Queue()
def __init__(self, **kwargs):
super(RootWidget, self).__init__(**kwargs)
def launchdaemon(self):
"""launch the bitmonerod daemon in rpc mode"""
bitmonerodloader()
def launchwallet(self):
"""create wallet if necessary and then launch in rpc mode"""
walletthread = Process(target=simplewalletloader, args=(self.input_name.text, self.input_pw.text, self.walletqueue))
walletthread.start()
walletthread.join()
self.walletname, self.address, self.rawaddress = self.walletqueue.get()
self.input_name.text = self.walletname
self.input_name.background_color = (0.1,0.8,0.8,1)
self.label_myaddress.text = self.address
def checkbalance(self):
"""get balance info from rpc"""
self.balance, self.unlockedbalance = checkbalancerpccall()
self.label_balance.text = self.balance
self.label_unlockedbalance.text = self.unlockedbalance
def selectaddress(self):
"""copy address to clipboard when user clicks"""
print('User clicked on ', self.rawaddress)
Clipboard.put(self.rawaddress)
def transferfunds(self):
"""initiate transfer of funds to new address"""
transferfundsrpccall(self.input_amount.text, self.input_address.text, self.input_mixin.text)
self.checkbalance()
class KivyWalletApp(App):
def build(self):
return RootWidget()
if __name__ == '__main__':
KivyWalletApp().run()