3 # Electrum - lightweight Bitcoin client
4 # Copyright (C) 2011 thomasv@gitorious
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.
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.
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/>.
22 from decimal import Decimal
25 protected_commands = ['payto', 'password', 'mktx', 'get_seed', 'importprivkey','signmessage', 'signrawtransaction', 'dumpprivkey', 'dumpprivkeys' ]
29 def __init__(self, wallet, interface):
31 self.interface = interface
33 def _run(self, method, args, password_getter):
34 if method in protected_commands:
35 self.password = apply(password_getter,())
36 f = eval('self.'+method)
40 def get_history(self, addr):
41 h = self.wallet.get_history(addr)
42 if h is None: h = self.wallet.interface.synchronous_get([ ('blockchain.address.get_history',[addr]) ])[0]
45 def listunspent(self):
46 l = self.wallet.get_unspent_coins()
47 for i in l: i["value"] = i["value"]*1e-8
50 def createrawtransaction(self, inputs, outputs):
51 # convert to own format
53 i['tx_hash'] = i['txid']
54 i['index'] = i['vout']
55 outputs = map(lambda x: (x[0],int(1e8*x[1])), outputs.items())
56 tx = Transaction.from_io(inputs, outputs)
59 def signrawtransaction(self, raw_tx, input_info, private_keys):
60 tx = Transaction(raw_tx)
61 unspent_coins = self.wallet.get_unspent_coins()
63 # convert private_keys to dict
65 for sec in private_keys:
66 address = bitcoin.address_from_private_key(sec)
70 for txin in tx.inputs:
71 # convert to own format
72 txin['tx_hash'] = txin['prevout_hash']
73 txin['index'] = txin['prevout_n']
75 for item in input_info:
76 if item.get('txid') == txin['tx_hash'] and item.get('vout') == txin['index']:
77 txin['raw_output_script'] = item['scriptPubKey']
78 txin['redeemScript'] = item.get('redeemScript')
79 txin['electrumKeyID'] = item.get('electrumKeyID')
82 for item in unspent_coins:
83 if txin['tx_hash'] == item['tx_hash'] and txin['index'] == item['index']:
84 txin['raw_output_script'] = item['raw_output_script']
87 # if neither, we might want to get it from the server..
92 if txin.get('electrumKeyID'):
93 n, for_change = txin.get('electrumKeyID')
94 sec = wallet.sequence.get_private_key(n, for_change, seed)
95 address = bitcoin.address_from_private_key(sec)
96 txin['address'] = address
97 private_keys[address] = sec
99 elif txin.get("redeemScript"):
100 txin['address'] = bitcoin.hash_160_to_bc_address(bitcoin.hash_160(txin.get("redeemScript").decode('hex')), 5)
102 elif txin.get("raw_output_script"):
103 addr = deserialize.get_address_from_output_script(txin.get("raw_output_script").decode('hex'))
104 sec = wallet.get_private_key(addr, self.password)
106 private_keys[addr] = sec
107 txin['address'] = addr
109 tx.sign( private_keys )
110 print_json({ "hex":str(tx),"complete":tx.is_complete})
112 def decoderawtransaction(self, raw):
113 tx = Transaction(raw)
114 print_json( tx.deserialize() )
116 def sendrawtransaction(self, raw):
117 tx = Transaction(raw)
118 r, h = wallet.sendtx( tx )
121 def createmultisig(self, num, pubkeys):
122 assert isinstance(pubkeys, list)
123 print_json( Transaction.multisig_script(pubkeys, num) )
125 def freeze(self,addr):
126 print_msg(self.wallet.freeze(addr))
128 def unfreeze(self,addr):
129 print_msg(self.wallet.unfreeze(addr))
131 def prioritize(self, addr):
132 print_msg(self.wallet.prioritize(addr))
134 def unprioritize(self, addr):
135 print_msg(self.wallet.unprioritize(addr))
137 def dumpprivkey(self, addr):
138 print_msg( self.wallet.get_private_key(addr, self.password) )
140 def dumpprivkeys(self, addresses):
141 print_json( self.wallet.get_private_keys(addresses, self.password) )
144 def validateaddress(self,addr):
145 is_valid = self.wallet.is_valid(addr)
146 out = { 'isvalid':is_valid }
148 is_mine = self.wallet.is_mine(addr)
149 out['address'] = addr
150 out['ismine'] = is_mine
152 out['pubkey'] = self.wallet.get_public_key(addr)
157 def balance(self, addresses = []):
159 c, u = self.wallet.get_balance()
161 print_msg(Decimal( c ) / 100000000 , Decimal( u ) / 100000000)
163 print_msg(Decimal( c ) / 100000000)
165 for addr in addresses:
166 c, u = wallet.get_addr_balance(addr)
168 print_msg("%s %s, %s" % (addr, str(Decimal(c)/100000000), str(Decimal(u)/100000000)))
170 print_msg("%s %s" % (addr, str(Decimal(c)/100000000)))
175 seed = self.wallet.decode_seed(self.password)
176 print_msg(seed + ' "' + ' '.join(mnemonic.mn_encode(seed)) + '"')
178 def importprivkey(self, sec):
180 addr = wallet.import_key(sec,self.password)
182 print_msg("Keypair imported: ", addr)
183 except BaseException as e:
184 print_msg("Error: Keypair import failed: " + str(e))
187 def sign_message(self, address, message):
188 print_msg(self.wallet.sign_message(address, message, self.password))
191 def verify_message(self, address, signature, message):
193 EC_KEY.verify_message(address, signature, message)
195 except BaseException as e:
196 print_error("Verification error: {0}".format(e))
200 def _mktx(self, to_address, amount, fee = None, change_addr = None, from_addr = None):
201 for k, v in self.wallet.labels.items():
204 print_msg("alias", to_address)
206 if change_addr and v == change_addr:
209 amount = int(10000000*amount)
210 if fee: fee = int(10000000*fee)
211 return self.wallet.mktx( [(to_address, amount)], self.password, fee , change_addr, from_addr)
214 def mktx(self, to_address, amount, fee = None, change_addr = None, from_addr = None):
215 tx = self._mktx(to_address, amount, fee, change_addr, from_addr)
216 out = {"hex":str(tx), "complete":tx.is_complete}
217 if not tx.is_complete:
218 out['input_info'] = repr(tx.input_info).replace(' ','')
222 def payto(self, to_address, amount, fee = None, change_addr = None, from_addr = None):
223 tx = self._mktx(to_address, amount, fee, change_addr, from_addr)
224 r, h = wallet.sendtx( tx )
231 for item in self.wallet.get_tx_history():
232 tx_hash, conf, is_mine, value, fee, balance, timestamp = item
234 time_str = datetime.datetime.fromtimestamp( timestamp).isoformat(' ')[:-3]
238 label, is_default_label = self.wallet.get_label(tx_hash)
239 if not label: label = tx_hash
240 else: label = label + ' '*(64 - len(label) )
242 print_msg("%17s"%time_str, " " + label + " " + format_satoshis(value)+ " "+ format_satoshis(balance))
243 print_msg("# balance: ", format_satoshis(balance))
246 def setlabel(self, tx, label):
247 self.wallet.labels[tx] = label
253 for addr in self.wallet.addressbook:
254 c[addr] = self.wallet.labels.get(addr)