2011-11-04 18:00:37 +01:00
#!/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/>.
2012-08-23 17:05:07 -07:00
import re
2012-12-05 10:24:30 +01:00
import sys , os , time
2012-08-25 14:11:50 -07:00
import optparse
2012-08-23 17:05:07 -07:00
2012-05-14 14:09:50 +02:00
try :
import ecdsa
2012-08-19 15:10:17 -07:00
except ImportError :
sys . exit ( " Error: python-ecdsa does not seem to be installed. Try ' sudo pip install ecdsa ' " )
2012-05-14 14:09:50 +02:00
try :
import aes
2012-08-19 15:10:17 -07:00
except ImportError :
sys . exit ( " Error: AES does not seem to be installed. Try ' sudo pip install slowaes ' " )
2012-05-14 14:09:50 +02:00
2012-05-30 16:46:04 +02:00
try :
2012-10-29 16:22:53 +01:00
from lib import *
2012-06-07 19:47:00 +02:00
except ImportError :
2012-10-29 16:22:53 +01:00
from electrum import *
2012-08-30 00:03:38 +02:00
2012-02-06 07:48:52 +01:00
from decimal import Decimal
2012-02-03 08:02:12 +01:00
2012-06-06 19:52:52 +02:00
known_commands = {
2012-06-18 22:19:47 +02:00
' help ' : ' Prints this help ' ,
' validateaddress ' : ' Check that the address is valid ' ,
' balance ' : " Display the balance of your wallet or of an address. \n Syntax: balance [<address>] " ,
2012-06-06 19:52:52 +02:00
' contacts ' : " Show your list of contacts " ,
2012-06-18 22:19:47 +02:00
' create ' : ' Create a wallet ' ,
' restore ' : ' Restore a wallet ' ,
' payto ' : """ Create and broadcast a transaction.
Syntax: payto <recipient> <amount> [label]
<recipient> can be a bitcoin address or a label
options: \n --fee, -f: set transaction fee \n --fromaddr, -s: send from address - \n --changeaddr, -c: send change to address
2012-06-06 19:52:52 +02:00
""" ,
' sendtx ' :
2012-06-18 22:19:47 +02:00
' Broadcasts a transaction to the network. \n Syntax: sendtx <tx> \n <tx> must be in hexadecimal. ' ,
2012-06-06 19:52:52 +02:00
' password ' :
2012-06-18 22:19:47 +02:00
" Changes your password " ,
2012-06-06 19:52:52 +02:00
' addresses ' :
2012-06-18 22:19:47 +02:00
""" Shows your list of addresses.
options:
-a: show all addresses, including change addresses
-k: show private keys
-b: show the balance of addresses """ ,
' history ' : " Shows the transaction history " ,
' label ' : ' Assign a label to an item \n Syntax: label <tx_hash> <label> ' ,
2012-06-06 19:52:52 +02:00
' mktx ' :
2012-06-18 22:19:47 +02:00
""" Create a signed transaction, password protected.
Syntax: mktx <recipient> <amount> [label]
options: \n --fee, -f: set transaction fee \n --fromaddr, -s: send from address - \n --changeaddr, -c: send change to address
2012-06-06 19:52:52 +02:00
""" ,
2012-12-05 18:18:47 +01:00
' signtx ' : " Sign an unsigned transaction created by a deseeded wallet \n Syntax: signtx <filename> " ,
2012-06-06 19:52:52 +02:00
' seed ' :
2012-06-18 22:19:47 +02:00
" Print the generation seed of your wallet. " ,
2013-01-05 21:28:12 +01:00
' importprivkey ' :
2012-06-18 22:19:47 +02:00
' Imports a key pair \n Syntax: import <address>:<privatekey> ' ,
2012-06-06 19:52:52 +02:00
' signmessage ' :
2012-08-26 22:15:09 +02:00
' Signs a message with a key \n Syntax: signmessage <address> <message> \n If you want to lead or end a message with spaces, or want double spaces inside the message make sure you quote the string. I.e. " Hello This is a weird String " ' ,
2012-06-06 19:52:52 +02:00
' verifymessage ' :
2012-08-26 22:15:09 +02:00
' Verifies a signature \n Syntax: verifymessage <address> <signature> <message> \n If you want to lead or end a message with spaces, or want double spaces inside the message make sure you quote the string. I.e. " Hello This is a weird String " ' ,
2012-06-06 19:52:52 +02:00
' eval ' :
" Run python eval() on an object \n Syntax: eval <expression> \n Example: eval \" wallet.aliases \" " ,
2012-10-26 17:35:35 +02:00
' get ' :
" Get config parameter. " ,
2012-10-20 10:23:34 +02:00
' set ' :
2012-10-26 17:35:35 +02:00
" Set config parameter. " ,
2012-06-06 19:52:52 +02:00
' deseed ' :
2012-06-18 22:19:47 +02:00
" Remove seed from the wallet. The seed is stored in a file that has the name of the wallet plus ' .seed ' " ,
2012-06-06 19:52:52 +02:00
' reseed ' :
2012-06-18 22:19:47 +02:00
" Restore seed of the wallet. The wallet must have no seed, and the seed must match the wallet ' s master public key. " ,
2012-06-06 19:52:52 +02:00
' freeze ' : ' ' ,
' unfreeze ' : ' ' ,
' prioritize ' : ' ' ,
' unprioritize ' : ' ' ,
}
2012-06-06 19:26:05 +02:00
2012-12-05 18:18:47 +01:00
offline_commands = [ ' password ' , ' mktx ' , ' signtx ' ,
2012-10-11 20:10:12 +02:00
' label ' , ' contacts ' ,
' help ' , ' validateaddress ' ,
' signmessage ' , ' verifymessage ' ,
2012-10-26 17:35:35 +02:00
' eval ' , ' set ' , ' get ' , ' create ' , ' addresses ' ,
2013-01-05 21:28:12 +01:00
' importprivkey ' , ' seed ' ,
2012-10-11 20:10:12 +02:00
' deseed ' , ' reseed ' ,
' freeze ' , ' unfreeze ' ,
' prioritize ' , ' unprioritize ' ]
2012-06-06 19:26:05 +02:00
2013-01-05 21:28:12 +01:00
protected_commands = [ ' payto ' , ' password ' , ' mktx ' , ' signtx ' , ' seed ' , ' importprivkey ' , ' signmessage ' ]
2012-03-23 13:55:27 +01:00
2012-10-12 01:50:54 +02:00
# get password routine
def prompt_password ( prompt , confirm = True ) :
import getpass
if sys . stdin . isatty ( ) :
password = getpass . getpass ( prompt )
if password and confirm :
password2 = getpass . getpass ( " Confirm: " )
if password != password2 :
sys . exit ( " Error: Passwords do not match. " )
else :
password = raw_input ( prompt )
if not password :
password = None
return password
2012-11-23 14:31:25 +01:00
def arg_parser ( ) :
2012-05-14 17:35:38 +02:00
usage = " usage: % prog [options] command \n Commands: " + ( ' , ' . join ( known_commands ) )
2012-08-25 14:16:21 -07:00
parser = optparse . OptionParser ( prog = usage )
2012-10-17 15:33:59 +02:00
parser . add_option ( " -g " , " --gui " , dest = " gui " , help = " User interface: qt, lite, gtk or text " )
2011-11-29 11:23:49 +01:00
parser . add_option ( " -w " , " --wallet " , dest = " wallet_path " , help = " wallet path (default: electrum.dat) " )
2012-05-13 10:19:28 +02:00
parser . add_option ( " -o " , " --offline " , action = " store_true " , dest = " offline " , default = False , help = " remain offline " )
2011-11-14 20:35:54 +01:00
parser . add_option ( " -a " , " --all " , action = " store_true " , dest = " show_all " , default = False , help = " show all addresses " )
parser . add_option ( " -b " , " --balance " , action = " store_true " , dest = " show_balance " , default = False , help = " show the balance at listed addresses " )
parser . add_option ( " -k " , " --keys " , action = " store_true " , dest = " show_keys " , default = False , help = " show the private keys of listed addresses " )
2011-12-18 22:49:33 +01:00
parser . add_option ( " -f " , " --fee " , dest = " tx_fee " , default = " 0.005 " , help = " set tx fee " )
2012-10-11 20:10:12 +02:00
parser . add_option ( " -F " , " --fromaddr " , dest = " from_addr " , default = None , help = " set source address for payto/mktx. if it isn ' t in the wallet, it will ask for the private key unless supplied in the format public_key:private_key. It ' s not saved in the wallet. " )
2012-02-08 09:36:19 +01:00
parser . add_option ( " -c " , " --changeaddr " , dest = " change_addr " , default = None , help = " set the change address for payto/mktx. default is a spare address, or the source address if it ' s not in the wallet " )
2012-10-11 20:10:12 +02:00
parser . add_option ( " -s " , " --server " , dest = " server " , default = None , help = " set server host:port:protocol, where protocol is t or h " )
2012-10-01 18:14:50 +02:00
parser . add_option ( " -p " , " --proxy " , dest = " proxy " , default = None , help = " set proxy [type:]host[:port], where type is socks4,socks5 or http " )
2012-11-04 12:27:01 +01:00
parser . add_option ( " -v " , " --verbose " , action = " store_true " , dest = " verbose " , default = False , help = " show debugging information " )
2012-12-17 15:08:34 +01:00
parser . add_option ( " -P " , " --portable " , action = " store_true " , dest = " portable " , default = False , help = " portable wallet " )
2013-01-02 16:03:54 +01:00
parser . add_option ( " -L " , " --lang " , dest = " language " , default = None , help = " defaut language used in GUI " )
2013-01-07 16:03:03 +00:00
parser . add_option ( " -u " , " --usb " , dest = " bitkey " , action = " store_true " , help = " Turn on support for hardware wallets (EXPERIMENTAL) " )
2012-11-23 14:31:25 +01:00
return parser
2012-11-18 11:34:52 +01:00
2011-11-04 18:00:37 +01:00
2012-11-18 11:34:52 +01:00
if __name__ == ' __main__ ' :
2012-11-23 14:31:25 +01:00
parser = arg_parser ( )
options , args = parser . parse_args ( )
2012-11-04 12:27:01 +01:00
set_verbosity ( options . verbose )
2012-10-29 16:22:53 +01:00
2012-10-11 20:10:12 +02:00
# config is an object passed to the various constructors (wallet, interface, gui)
2012-11-18 11:34:52 +01:00
if ' ANDROID_DATA ' in os . environ :
2012-12-17 17:51:52 +01:00
config_options = { ' wallet_path ' : " /sdcard/electrum.dat " , ' portable ' : True , ' verbose ' : True , ' gui ' : ' android ' }
2012-11-18 11:34:52 +01:00
else :
2012-11-19 14:05:42 +01:00
config_options = eval ( str ( options ) )
for k , v in config_options . items ( ) :
if v is None : config_options . pop ( k )
2012-11-18 11:34:52 +01:00
2012-11-19 14:05:42 +01:00
config = SimpleConfig ( config_options )
2012-10-11 20:10:12 +02:00
wallet = Wallet ( config )
2012-03-12 17:55:33 +01:00
2012-02-14 12:45:39 +01:00
if len ( args ) == 0 :
url = None
cmd = ' gui '
elif len ( args ) == 1 and re . match ( ' ^bitcoin: ' , args [ 0 ] ) :
url = args [ 0 ]
cmd = ' gui '
else :
cmd = args [ 0 ]
firstarg = args [ 1 ] if len ( args ) > 1 else ' '
2012-08-22 11:36:04 -07:00
#this entire if/else block is just concerned with importing the
#right GUI toolkit based the GUI command line option given
2012-02-14 12:45:39 +01:00
if cmd == ' gui ' :
2012-10-19 10:26:35 +02:00
pref_gui = config . get ( ' gui ' , ' classic ' )
2012-10-11 20:10:12 +02:00
if pref_gui == ' gtk ' :
2012-06-06 15:18:03 +02:00
try :
import lib . gui as gui
2012-06-07 19:47:00 +02:00
except ImportError :
2012-06-06 15:18:03 +02:00
import electrum . gui as gui
2012-10-19 10:26:35 +02:00
elif pref_gui in [ ' classic ' , ' qt ' ] :
2012-06-06 15:18:03 +02:00
try :
2012-06-07 14:13:51 +02:00
import lib . gui_qt as gui
2012-06-07 19:47:00 +02:00
except ImportError :
2012-06-06 15:18:03 +02:00
import electrum . gui_qt as gui
2012-10-11 20:10:12 +02:00
elif pref_gui == ' lite ' :
2012-08-18 10:20:35 +02:00
try :
2012-10-11 13:43:04 +02:00
import lib . gui_lite as gui
2012-08-18 10:20:35 +02:00
except ImportError :
2012-10-11 13:43:04 +02:00
import electrum . gui_lite as gui
2012-10-17 09:24:31 +02:00
elif pref_gui == ' text ' :
try :
import lib . gui_text as gui
except ImportError :
import electrum . gui_text as gui
2012-11-18 11:34:52 +01:00
elif pref_gui == ' android ' :
try :
import lib . gui_android as gui
except ImportError :
import electrum . gui_android as gui
2012-02-14 12:45:39 +01:00
else :
2012-10-11 20:10:12 +02:00
sys . exit ( " Error: Unknown GUI: " + pref_gui )
2012-02-11 13:14:12 +01:00
2012-11-20 15:30:46 +01:00
2012-10-22 11:34:21 +02:00
interface = Interface ( config , True )
2012-11-20 15:30:46 +01:00
wallet . interface = interface
2012-10-26 09:08:06 +02:00
interface . start ( )
2013-01-03 21:36:25 +01:00
if interface . is_connected :
interface . send ( [ ( ' server.peers.subscribe ' , [ ] ) ] )
2012-10-26 09:08:06 +02:00
2013-01-02 16:12:00 +01:00
set_language ( config . get ( ' language ' ) )
2012-11-20 17:21:57 +01:00
gui = gui . ElectrumGui ( wallet , config )
2012-11-20 15:30:46 +01:00
found = config . wallet_file_exists
if not found :
a = gui . restore_or_create ( )
if not a : exit ( )
2012-11-20 21:36:06 +01:00
# select a server.
s = gui . network_dialog ( )
2012-11-20 15:30:46 +01:00
if a == ' create ' :
wallet . new_seed ( None )
wallet . init_mpk ( wallet . seed )
else :
# ask for seed and gap.
if not gui . seed_dialog ( ) : exit ( )
wallet . init_mpk ( wallet . seed )
2012-11-23 19:25:35 +01:00
# generate the first addresses, in case we are offline
2012-11-23 19:31:45 +01:00
if s is None or a == ' create ' :
wallet . synchronize ( )
2012-11-20 21:46:45 +01:00
if a == ' create ' :
# display seed
gui . show_seed ( )
2012-11-20 15:30:46 +01:00
2012-11-04 20:53:27 +01:00
verifier = WalletVerifier ( interface , config )
wallet . set_verifier ( verifier )
2012-11-24 20:31:07 +01:00
synchronizer = WalletSynchronizer ( wallet , config )
synchronizer . start ( )
2012-02-14 09:52:03 +01:00
2012-11-20 15:30:46 +01:00
if not found and a == ' restore ' and s is not None :
try :
2012-11-20 21:36:06 +01:00
keep_it = gui . restore_wallet ( )
wallet . fill_addressbook ( )
2012-11-20 15:30:46 +01:00
except :
import traceback
traceback . print_exc ( file = sys . stdout )
exit ( )
2012-10-26 09:08:06 +02:00
2012-11-20 21:36:06 +01:00
if not keep_it : exit ( )
2012-10-26 09:08:06 +02:00
2012-11-20 21:46:45 +01:00
if not found :
gui . password_dialog ( )
2012-11-20 21:36:06 +01:00
wallet . save ( )
2012-11-20 15:30:46 +01:00
verifier . start ( )
2012-02-14 12:45:39 +01:00
gui . main ( url )
2011-11-09 23:21:27 +01:00
wallet . save ( )
2012-11-24 20:31:07 +01:00
2012-11-05 23:10:38 +01:00
verifier . stop ( )
synchronizer . stop ( )
2012-11-24 20:31:07 +01:00
interface . stop ( )
2012-12-05 10:24:30 +01:00
# we use daemon threads, their termination is enforced.
# this sleep command gives them time to terminate cleanly.
time . sleep ( 0.1 )
2011-11-10 09:34:27 +01:00
sys . exit ( 0 )
2011-11-04 18:00:37 +01:00
2012-01-15 18:45:30 +01:00
if cmd not in known_commands :
cmd = ' help '
2012-10-11 20:10:12 +02:00
if not config . wallet_file_exists and cmd not in [ ' help ' , ' create ' , ' restore ' ] :
2012-11-23 18:48:56 +01:00
print_msg ( " Error: Wallet file not found. " )
print_msg ( " Type ' electrum create ' to create a new wallet, or provide a path to a wallet with the -w option " )
2011-11-16 18:26:06 +03:00
sys . exit ( 0 )
2012-02-21 14:36:45 +01:00
if cmd in [ ' create ' , ' restore ' ] :
2012-10-11 20:10:12 +02:00
if config . wallet_file_exists :
2012-08-19 17:16:35 -07:00
sys . exit ( " Error: Remove the existing wallet first! " )
2012-07-06 21:45:57 -07:00
password = prompt_password ( " Password (hit return if you do not wish to encrypt your wallet): " )
2011-11-04 18:00:37 +01:00
2012-10-11 20:10:12 +02:00
server = config . get ( ' server ' )
if not server : server = pick_random_server ( )
w_host , w_port , w_protocol = server . split ( ' : ' )
2012-03-31 06:39:23 +02:00
host = raw_input ( " server (default: %s ): " % w_host )
port = raw_input ( " port (default: %s ): " % w_port )
protocol = raw_input ( " protocol [t=tcp;h=http;n=native] (default: %s ): " % w_protocol )
2012-02-06 07:48:52 +01:00
fee = raw_input ( " fee (default: %s ): " % ( str ( Decimal ( wallet . fee ) / 100000000 ) ) )
2012-02-19 14:31:21 +02:00
gap = raw_input ( " gap limit (default 5): " )
2012-03-31 06:39:23 +02:00
if host : w_host = host
if port : w_port = port
if protocol : w_protocol = protocol
2012-10-11 20:10:12 +02:00
wallet . config . set_key ( ' server ' , w_host + ' : ' + w_port + ' : ' + w_protocol )
2012-02-21 14:36:45 +01:00
if fee : wallet . fee = float ( fee )
2012-02-19 14:31:21 +02:00
if gap : wallet . gap_limit = int ( gap )
2012-02-21 14:36:45 +01:00
if cmd == ' restore ' :
seed = raw_input ( " seed: " )
try :
seed . decode ( ' hex ' )
except :
2012-07-07 09:24:52 -07:00
print_error ( " Warning: Not hex, trying decode. " )
2012-11-04 19:40:17 +01:00
seed = mnemonic_decode ( seed . split ( ' ' ) )
2012-02-21 14:36:45 +01:00
if not seed :
2012-08-19 17:17:47 -07:00
sys . exit ( " Error: No seed " )
2012-02-21 14:36:45 +01:00
wallet . seed = str ( seed )
2012-03-23 20:58:54 +01:00
wallet . init_mpk ( wallet . seed )
2012-05-13 10:19:28 +02:00
if not options . offline :
2012-11-04 21:12:08 +01:00
interface = Interface ( config )
interface . start ( )
wallet . interface = interface
verifier = WalletVerifier ( interface , config )
wallet . set_verifier ( verifier )
2012-11-23 18:48:56 +01:00
print_msg ( " Recovering wallet... " )
2012-11-05 13:12:22 +01:00
WalletSynchronizer ( wallet , config ) . start ( )
2012-05-13 10:19:28 +02:00
wallet . update ( )
if wallet . is_found ( ) :
2012-11-23 18:48:56 +01:00
print_msg ( " Recovery successful " )
2012-05-13 10:19:28 +02:00
else :
2012-11-23 18:48:56 +01:00
print_msg ( " Warning: Found no history for this wallet " )
2012-09-20 16:46:11 +07:00
else :
wallet . synchronize ( )
2012-05-13 10:19:28 +02:00
wallet . fill_addressbook ( )
wallet . save ( )
2012-11-23 18:48:56 +01:00
print_msg ( " Wallet saved in ' %s ' " % wallet . config . path )
2011-11-06 11:13:58 +01:00
else :
wallet . new_seed ( None )
2012-03-23 20:58:54 +01:00
wallet . init_mpk ( wallet . seed )
wallet . synchronize ( ) # there is no wallet thread
2012-02-21 17:13:34 +01:00
wallet . save ( )
2012-11-23 18:48:56 +01:00
print_msg ( " Your wallet generation seed is: " + wallet . seed )
print_msg ( " Please keep it in a safe place; if you lose it, you will not be able to restore your wallet. " )
print_msg ( " Equivalently, your wallet seed can be stored and recovered with the following mnemonic code: " )
print_msg ( " \" " + ' ' . join ( mnemonic_encode ( wallet . seed ) ) + " \" " )
print_msg ( " Wallet saved in ' %s ' " % wallet . config . path )
2012-05-17 08:49:30 +02:00
if password :
wallet . update_password ( wallet . seed , None , password )
2011-11-04 18:00:37 +01:00
2011-11-12 00:07:41 +01:00
# check syntax
2012-02-08 09:36:19 +01:00
if cmd in [ ' payto ' , ' mktx ' ] :
2011-11-12 00:07:41 +01:00
try :
2012-02-08 09:36:19 +01:00
to_address = args [ 1 ]
amount = int ( 100000000 * Decimal ( args [ 2 ] ) )
2012-02-08 04:22:18 +01:00
change_addr = None
2012-02-08 09:36:19 +01:00
label = ' ' . join ( args [ 3 : ] )
2011-12-18 22:49:33 +01:00
if options . tx_fee :
options . tx_fee = int ( 100000000 * Decimal ( options . tx_fee ) )
2011-11-12 00:07:41 +01:00
except :
2011-11-16 18:12:13 +03:00
firstarg = cmd
cmd = ' help '
2011-11-12 00:07:41 +01:00
2011-11-14 20:35:54 +01:00
# open session
2012-05-13 10:19:28 +02:00
if cmd not in offline_commands and not options . offline :
2012-10-22 11:34:21 +02:00
interface = Interface ( config )
2012-11-05 23:10:38 +01:00
interface . register_callback ( ' connected ' , lambda : sys . stderr . write ( " Connected to " + interface . connection_msg + " \n " ) )
2012-10-22 11:34:21 +02:00
interface . start ( )
wallet . interface = interface
2012-11-05 23:10:38 +01:00
synchronizer = WalletSynchronizer ( wallet , config )
synchronizer . start ( )
2012-03-23 16:34:34 +01:00
wallet . update ( )
2011-11-14 20:35:54 +01:00
wallet . save ( )
2012-02-11 06:48:44 +01:00
# check if --from_addr not in wallet (for mktx/payto)
is_temporary = False
from_addr = None
if options . from_addr :
from_addr = options . from_addr
if from_addr not in wallet . all_addresses ( ) :
is_temporary = True
2012-10-02 13:15:10 +02:00
# important warning
if cmd == ' addresses ' and options . show_keys :
2012-11-23 18:48:56 +01:00
print_msg ( " WARNING: ALL your private keys are secret. " )
print_msg ( " Exposing a single private key can compromise your entire wallet! " )
print_msg ( " In particular, DO NOT use ' redeem private key ' services proposed by third parties. " )
2012-10-02 13:15:10 +02:00
2011-11-14 20:35:54 +01:00
# commands needing password
2012-03-23 13:55:27 +01:00
if cmd in protected_commands or ( cmd == ' addresses ' and options . show_keys ) :
2013-01-02 13:39:50 +01:00
if wallet . use_encryption and not is_temporary :
password = prompt_password ( ' Password: ' , False )
if not password :
print_msg ( " Error: Password required " )
exit ( 1 )
# check password
try :
2013-01-06 09:41:06 +01:00
seed = wallet . decode_seed ( password )
2013-01-02 13:39:50 +01:00
except :
print_msg ( " Error: This password does not decode this wallet. " )
exit ( 1 )
else :
password = None
2013-01-06 15:57:01 +01:00
seed = wallet . seed
2011-12-20 14:22:31 +01:00
2013-01-05 21:28:12 +01:00
if cmd == ' importprivkey ' :
2012-08-01 21:52:52 +02:00
# See if they specificed a key on the cmd line, if not prompt
if len ( args ) > 1 :
2013-01-05 21:28:12 +01:00
sec = args [ 1 ]
2012-08-01 21:52:52 +02:00
else :
2013-01-05 21:28:12 +01:00
sec = prompt_password ( ' Enter PrivateKey (will not echo): ' , False )
2012-05-30 14:42:30 +02:00
try :
2013-01-05 21:28:12 +01:00
addr = wallet . import_key ( sec , password )
2012-05-30 14:42:30 +02:00
wallet . save ( )
2013-01-05 21:28:12 +01:00
print_msg ( " Keypair imported: " , addr )
2012-11-27 23:32:39 +01:00
except BaseException as e :
print_msg ( " Error: Keypair import failed: " + str ( e ) )
2011-12-20 12:37:48 +01:00
2012-07-17 22:50:20 +02:00
if cmd == ' help ' :
2011-11-16 18:12:13 +03:00
cmd2 = firstarg
if cmd2 not in known_commands :
2012-07-17 22:50:20 +02:00
parser . print_help ( )
2012-11-23 18:48:56 +01:00
print_msg ( " Type ' electrum help <command> ' to see the help for a specific command " )
print_msg ( " Type ' electrum --help ' to see the list of options " )
print_msg ( " List of commands: " , ' , ' . join ( known_commands ) )
2012-06-06 19:52:52 +02:00
else :
2012-11-23 18:48:56 +01:00
print_msg ( known_commands [ cmd2 ] )
2011-11-16 18:12:13 +03:00
elif cmd == ' seed ' :
2012-11-23 18:48:56 +01:00
print_msg ( seed + ' " ' + ' ' . join ( mnemonic_encode ( seed ) ) + ' " ' )
2011-11-14 20:35:54 +01:00
2012-05-13 00:43:22 +02:00
elif cmd == ' deseed ' :
2012-05-13 01:32:28 +02:00
if not wallet . seed :
2012-11-27 23:32:39 +01:00
print_msg ( " Error: This wallet has no seed " )
2012-05-13 02:36:44 +02:00
elif wallet . use_encryption :
2012-11-27 23:32:39 +01:00
print_msg ( " Error: This wallet is encrypted " )
2012-05-13 00:43:22 +02:00
else :
2012-11-21 22:57:11 +01:00
ns = wallet . config . path + ' .seed '
2012-11-23 18:48:56 +01:00
print_msg ( " Warning: you are going to extract the seed from ' %s ' \n The seed will be saved in ' %s ' " % ( wallet . config . path , ns ) )
2012-05-13 01:32:28 +02:00
if raw_input ( " Are you sure you want to continue? (y/n) " ) in [ ' y ' , ' Y ' , ' yes ' ] :
f = open ( ns , ' w ' )
2012-05-17 18:10:36 +02:00
f . write ( repr ( { ' seed ' : wallet . seed , ' imported_keys ' : wallet . imported_keys } ) + " \n " )
2012-05-13 01:32:28 +02:00
f . close ( )
wallet . seed = ' '
2012-05-17 18:10:36 +02:00
for k in wallet . imported_keys . keys ( ) : wallet . imported_keys [ k ] = ' '
2012-05-13 01:32:28 +02:00
wallet . save ( )
2012-11-23 18:48:56 +01:00
print_msg ( " Done. " )
2012-05-13 01:32:28 +02:00
else :
2012-11-27 23:32:39 +01:00
print_msg ( " Action canceled. " )
2012-05-13 01:32:28 +02:00
elif cmd == ' reseed ' :
if wallet . seed :
2012-11-23 18:48:56 +01:00
print_msg ( " Warning: This wallet already has a seed " , wallet . seed )
2012-05-13 01:32:28 +02:00
else :
2012-11-21 22:57:11 +01:00
ns = wallet . config . path + ' .seed '
2012-05-13 01:32:28 +02:00
try :
f = open ( ns , ' r ' )
2012-05-17 18:10:36 +02:00
data = f . read ( )
2012-05-13 01:32:28 +02:00
f . close ( )
2012-08-19 18:19:59 -07:00
except IOError :
sys . exit ( " Error: Seed file not found " )
2012-05-17 18:10:36 +02:00
try :
import ast
d = ast . literal_eval ( data )
seed = d [ ' seed ' ]
imported_keys = d . get ( ' imported_keys ' , { } )
except :
2012-08-19 18:19:59 -07:00
sys . exit ( " Error: Error with seed file " )
2012-05-13 01:32:28 +02:00
mpk = wallet . master_public_key
wallet . seed = seed
2012-05-17 18:10:36 +02:00
wallet . imported_keys = imported_keys
2012-05-13 01:32:28 +02:00
wallet . use_encryption = False
wallet . init_mpk ( seed )
if mpk == wallet . master_public_key :
wallet . save ( )
2012-11-23 18:48:56 +01:00
print_msg ( " Done: " + wallet . config . path )
2012-05-13 01:32:28 +02:00
else :
2012-11-27 23:32:39 +01:00
print_msg ( " Error: Master public key does not match " )
2012-05-13 01:32:28 +02:00
2011-11-17 01:55:29 +01:00
elif cmd == ' validateaddress ' :
addr = args [ 1 ]
2012-11-23 18:48:56 +01:00
print_msg ( wallet . is_valid ( addr ) )
2011-11-17 01:55:29 +01:00
2011-11-16 17:16:36 +03:00
elif cmd == ' balance ' :
2012-01-16 02:02:48 +02:00
try :
addrs = args [ 1 : ]
except :
pass
if addrs == [ ] :
c , u = wallet . get_balance ( )
if u :
2012-11-23 18:48:56 +01:00
print_msg ( Decimal ( c ) / 100000000 , Decimal ( u ) / 100000000 )
2012-01-16 02:02:48 +02:00
else :
2012-11-23 18:48:56 +01:00
print_msg ( Decimal ( c ) / 100000000 )
2011-11-04 18:00:37 +01:00
else :
2012-01-16 02:02:48 +02:00
for addr in addrs :
c , u = wallet . get_addr_balance ( addr )
if u :
2012-11-23 18:48:56 +01:00
print_msg ( " %s %s , %s " % ( addr , str ( Decimal ( c ) / 100000000 ) , str ( Decimal ( u ) / 100000000 ) ) )
2012-01-16 02:02:48 +02:00
else :
2012-11-23 18:48:56 +01:00
print_msg ( " %s %s " % ( addr , str ( Decimal ( c ) / 100000000 ) ) )
2011-11-04 18:00:37 +01:00
2011-11-14 20:35:54 +01:00
elif cmd in [ ' contacts ' ] :
2011-11-12 00:07:41 +01:00
for addr in wallet . addressbook :
2012-11-23 18:48:56 +01:00
print_msg ( addr , " " , wallet . labels . get ( addr ) )
2011-11-12 00:07:41 +01:00
2012-02-06 18:13:33 +01:00
elif cmd == ' eval ' :
2012-11-23 18:48:56 +01:00
print_msg ( eval ( args [ 1 ] ) )
2012-02-06 18:55:25 +01:00
wallet . save ( )
2012-02-03 17:38:43 +01:00
2012-10-26 17:35:35 +02:00
elif cmd == ' get ' :
key = args [ 1 ]
2012-11-23 18:48:56 +01:00
print_msg ( wallet . config . get ( key ) )
2012-10-26 17:35:35 +02:00
2012-10-20 10:23:34 +02:00
elif cmd == ' set ' :
key , value = args [ 1 : 3 ]
2012-10-28 09:19:07 +01:00
if key not in [ ' seed ' , ' seed_version ' , ' master_public_key ' , ' use_encryption ' ] :
2012-10-20 10:23:34 +02:00
wallet . config . set_key ( key , value , True )
2012-11-23 18:48:56 +01:00
print_msg ( True )
2012-10-20 10:23:34 +02:00
else :
2012-11-23 18:48:56 +01:00
print_msg ( False )
2012-10-20 10:23:34 +02:00
2011-11-14 20:35:54 +01:00
elif cmd in [ ' addresses ' ] :
2011-12-18 22:49:33 +01:00
for addr in wallet . all_addresses ( ) :
2011-11-14 20:35:54 +01:00
if options . show_all or not wallet . is_change ( addr ) :
2012-06-07 11:03:13 +02:00
2012-06-07 16:14:08 +02:00
flags = wallet . get_address_flags ( addr )
2012-06-07 11:03:13 +02:00
label = wallet . labels . get ( addr , ' ' )
2012-06-07 16:14:08 +02:00
2012-06-07 11:03:13 +02:00
if label : label = " \" %s \" " % label
2011-11-14 20:35:54 +01:00
if options . show_balance :
2011-12-21 17:58:14 +01:00
h = wallet . history . get ( addr , [ ] )
2012-06-07 11:03:13 +02:00
#ni = no = 0
#for item in h:
# if item['is_input']: ni += 1
# else: no += 1
b = format_satoshis ( wallet . get_addr_balance ( addr ) [ 0 ] )
2011-11-14 20:35:54 +01:00
else : b = ' '
2012-06-08 20:51:10 +02:00
m_addr = " %34s " % addr
2011-12-20 14:07:37 +01:00
if options . show_keys :
2012-06-08 20:51:10 +02:00
m_addr + = ' : ' + str ( wallet . get_private_key_base58 ( addr , password ) )
2012-11-23 18:48:56 +01:00
print_msg ( flags , m_addr , b , label )
2011-11-04 18:00:37 +01:00
if cmd == ' history ' :
2012-11-16 14:39:31 +01:00
import datetime
for item in wallet . get_tx_history ( ) :
tx_hash , conf , is_mine , value , fee , balance , timestamp = item
2011-11-04 18:00:37 +01:00
try :
2012-11-16 14:39:31 +01:00
time_str = datetime . datetime . fromtimestamp ( timestamp ) . isoformat ( ' ' ) [ : - 3 ]
2011-11-04 18:00:37 +01:00
except :
2012-11-16 14:39:31 +01:00
time_str = " ---- "
label , is_default_label = wallet . get_label ( tx_hash )
if not label : label = tx_hash
2011-11-04 18:00:37 +01:00
else : label = label + ' ' * ( 64 - len ( label ) )
2012-11-23 18:48:56 +01:00
print_msg ( " %17s " % time_str , " " + label + " " + format_satoshis ( value ) + " " + format_satoshis ( balance ) )
print_msg ( " # balance: " , format_satoshis ( balance ) )
2011-11-04 18:00:37 +01:00
elif cmd == ' label ' :
try :
2011-11-14 20:35:54 +01:00
tx = args [ 1 ]
label = ' ' . join ( args [ 2 : ] )
2011-11-04 18:00:37 +01:00
except :
2012-11-27 23:32:39 +01:00
print_msg ( " Error. Syntax: label <tx_hash> <text> " )
2011-11-10 09:34:27 +01:00
sys . exit ( 1 )
2011-11-04 18:00:37 +01:00
wallet . labels [ tx ] = label
wallet . save ( )
2012-02-08 09:36:19 +01:00
elif cmd in [ ' payto ' , ' mktx ' ] :
2012-02-11 06:48:44 +01:00
if from_addr and is_temporary :
if from_addr . find ( " : " ) == - 1 :
2012-07-06 21:45:57 -07:00
keypair = from_addr + " : " + prompt_password ( ' Private key: ' , False )
2012-02-11 06:48:44 +01:00
else :
keypair = from_addr
from_addr = keypair . split ( ' : ' ) [ 0 ]
if not wallet . import_key ( keypair , password ) :
2012-11-27 23:32:39 +01:00
print_msg ( " Error: Invalid key pair " )
2012-02-11 06:48:44 +01:00
exit ( 1 )
wallet . history [ from_addr ] = interface . retrieve_history ( from_addr )
wallet . update_tx_history ( )
change_addr = from_addr
2012-02-10 13:23:39 +01:00
2012-02-08 09:36:19 +01:00
if options . change_addr :
change_addr = options . change_addr
2012-02-10 13:23:39 +01:00
2011-11-12 00:07:41 +01:00
for k , v in wallet . labels . items ( ) :
if v == to_address :
to_address = k
2012-11-23 18:48:56 +01:00
print_msg ( " alias " , to_address )
2011-11-12 00:07:41 +01:00
break
2012-02-08 04:22:18 +01:00
if change_addr and v == change_addr :
change_addr = k
2011-12-18 22:49:33 +01:00
try :
2012-12-05 16:41:39 +01:00
tx = wallet . mktx ( [ ( to_address , amount ) ] , label , password ,
2012-02-10 13:23:39 +01:00
fee = options . tx_fee , change_addr = change_addr , from_addr = from_addr )
except :
import traceback
traceback . print_exc ( file = sys . stdout )
2011-12-18 22:49:33 +01:00
tx = None
2012-02-08 09:36:19 +01:00
if tx and cmd == ' payto ' :
2011-11-16 17:16:36 +03:00
r , h = wallet . sendtx ( tx )
2012-11-23 18:48:56 +01:00
print_msg ( h )
2011-11-16 17:16:36 +03:00
else :
2012-11-23 18:48:56 +01:00
print_msg ( tx )
2011-11-16 17:16:36 +03:00
2012-02-10 13:23:39 +01:00
if is_temporary :
wallet . imported_keys . pop ( from_addr )
2012-02-11 05:50:07 +01:00
del ( wallet . history [ from_addr ] )
2012-02-10 13:23:39 +01:00
wallet . save ( )
2012-12-05 18:18:47 +01:00
elif cmd == ' signtx ' :
import ast
filename = args [ 1 ]
f = open ( filename , ' r ' )
d = ast . literal_eval ( f . read ( ) )
f . close ( )
inputs = d [ ' inputs ' ]
outputs = d [ ' outputs ' ]
tx = wallet . signed_tx ( inputs , outputs , password )
print_msg ( tx )
2011-12-15 15:41:50 +01:00
elif cmd == ' sendtx ' :
2011-11-16 17:16:36 +03:00
tx = args [ 1 ]
r , h = wallet . sendtx ( tx )
2012-11-23 18:48:56 +01:00
print_msg ( h )
2011-11-04 18:00:37 +01:00
elif cmd == ' password ' :
2012-07-06 21:45:57 -07:00
new_password = prompt_password ( ' New password: ' )
wallet . update_password ( seed , password , new_password )
2011-11-04 18:00:37 +01:00
2012-02-01 20:27:03 +01:00
elif cmd == ' signmessage ' :
2012-07-17 22:53:06 +02:00
if len ( args ) < 3 :
2012-11-27 23:32:39 +01:00
print_msg ( " Error: Invalid usage of signmessage. " )
2012-11-23 18:48:56 +01:00
print_msg ( known_commands [ cmd ] )
2012-07-17 22:53:06 +02:00
sys . exit ( 1 )
2012-06-12 10:46:21 +02:00
address = args [ 1 ]
message = ' ' . join ( args [ 2 : ] )
if len ( args ) > 3 :
2012-11-23 18:48:56 +01:00
print_msg ( " Warning: Message was reconstructed from several arguments: " , repr ( message ) )
print_msg ( wallet . sign_message ( address , message , password ) )
2012-02-01 20:27:03 +01:00
elif cmd == ' verifymessage ' :
2012-06-18 22:23:52 +02:00
try :
address = args [ 1 ]
signature = args [ 2 ]
message = ' ' . join ( args [ 3 : ] )
except :
2012-11-27 23:32:39 +01:00
print_msg ( " Error: Not all parameters were given, displaying help instead. " )
2012-11-23 18:48:56 +01:00
print_msg ( known_commands [ cmd ] )
2012-06-18 22:23:52 +02:00
sys . exit ( 1 )
2012-06-12 10:46:21 +02:00
if len ( args ) > 4 :
2012-11-23 18:48:56 +01:00
print_msg ( " Warning: Message was reconstructed from several arguments: " , repr ( message ) )
2012-02-03 11:48:09 +01:00
try :
wallet . verify_message ( address , signature , message )
2012-11-23 18:48:56 +01:00
print_msg ( True )
2012-08-26 23:35:38 +02:00
except BaseException as e :
2012-11-18 11:34:52 +01:00
print_error ( " Verification error: {0} " . format ( e ) )
2012-11-23 18:48:56 +01:00
print_msg ( False )
2012-06-06 19:26:05 +02:00
elif cmd == ' freeze ' :
addr = args [ 1 ]
2012-11-23 18:48:56 +01:00
print_msg ( wallet . freeze ( addr ) )
2012-06-07 11:18:11 +02:00
2012-06-06 19:26:05 +02:00
elif cmd == ' unfreeze ' :
addr = args [ 1 ]
2012-11-23 18:48:56 +01:00
print_msg ( wallet . unfreeze ( addr ) )
2012-06-06 19:26:05 +02:00
elif cmd == ' prioritize ' :
addr = args [ 1 ]
2012-11-23 18:48:56 +01:00
print_msg ( wallet . prioritize ( addr ) )
2012-06-06 19:26:05 +02:00
elif cmd == ' unprioritize ' :
addr = args [ 1 ]
2012-11-23 18:48:56 +01:00
print_msg ( wallet . unprioritize ( addr ) )
2012-02-01 20:27:03 +01:00
2012-11-05 23:10:38 +01:00
if cmd not in offline_commands and not options . offline :
synchronizer . stop ( )