updated coblee description.
[electrum-nvc.git] / remote_wallet.py
1 #!/usr/bin/env python
2 #
3 # Electrum - lightweight Bitcoin client
4 # Copyright (C) 2011 thomasv@gitorious
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 import time, thread, sys, socket
20
21 # see http://code.google.com/p/jsonrpclib/
22 import jsonrpclib
23 from wallet import Wallet
24 try:
25     from lib.util import print_error
26 except ImportError:
27     from electrum.util import print_error
28
29 """
30 Simple wallet daemon for webservers.
31 - generates new addresses on request
32 - private keys are not needed in order to generate new addresses. A neutralized wallet can be used (seed removed)
33 - no gap limit: use 'getnum' to know how many addresses have been created.
34
35 todo:
36 - return the max gap
37 - add expiration date
38
39 """
40
41
42 host = 'ecdsa.org'
43 port = 8444
44 wallet_path = 'wallet_path'
45 username = 'foo'
46 password = 'bar'
47 wallet = Wallet()
48 stopping = False
49
50
51
52 from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCRequestHandler
53 import SimpleXMLRPCServer
54
55 class authHandler(SimpleJSONRPCRequestHandler):
56     def parse_request(self):
57         if SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.parse_request(self):
58             if self.authenticate(self.headers):
59                 return True
60             else:
61                 self.send_error(401, 'Authentication failed')
62             return False
63
64     def authenticate(self, headers):
65         from base64 import b64decode
66         basic, _, encoded = headers.get('Authorization').partition(' ')
67         assert basic == 'Basic', 'Only basic authentication supported'
68         x_username, _, x_password = b64decode(encoded).partition(':')
69         return username == x_username and password == x_password
70
71
72 def do_stop():
73     global stopping
74     stopping = True
75
76 def get_new_address():
77     a = wallet.create_new_address(False)
78     wallet.save()
79     return a
80
81 def get_num():
82     return len(wallet.addresses)
83
84 def get_mpk():
85     return wallet.master_public_key.encode('hex')
86
87
88
89 if __name__ == '__main__':
90
91     if len(sys.argv)>1:
92         import jsonrpclib
93         server = jsonrpclib.Server('http://%s:%s@%s:%d'%(username, password, host, port))
94         cmd = sys.argv[1]
95
96         try:
97             if cmd == 'getnum':
98                 out = server.getnum()
99             elif cmd == 'getkey':
100                 out = server.getkey()
101             elif cmd == 'getnewaddress':
102                 out = server.getnewaddress()
103             elif cmd == 'stop':
104                 out = server.stop()
105         except socket.error:
106             print_error("Server not running")
107             sys.exit(1)
108         print out
109         sys.exit(0)
110
111     else:
112
113         wallet.set_path(wallet_path)
114         wallet.read()
115
116         def server_thread():
117             from SocketServer import ThreadingMixIn
118             from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer
119             server = SimpleJSONRPCServer(( host, port), requestHandler=authHandler)
120             server.register_function(get_new_address, 'getnewaddress')
121             server.register_function(get_num, 'getnum')
122             server.register_function(get_mpk, 'getkey')
123             server.register_function(do_stop, 'stop')
124             server.serve_forever()
125
126         thread.start_new_thread(server_thread, ())
127         while not stopping: time.sleep(0.1)
128
129
130
131