electrum-bitcoinprivate/lib/commands.py

518 lines
25 KiB
Python
Raw Normal View History

#!/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 sys
import datetime
import time
import copy
import argparse
2014-07-24 01:59:13 -07:00
from util import print_msg, format_satoshis, print_stderr
2015-05-30 03:35:58 -07:00
from util import StoreDict
from bitcoin import is_valid, hash_160_to_bc_address, hash_160
from decimal import Decimal
import bitcoin
from transaction import Transaction
2013-10-03 03:39:42 -07:00
2013-10-03 03:39:42 -07:00
class Command:
def __init__(self, name, requires_network, requires_wallet, requires_password, params, options, help, description):
2013-10-03 03:39:42 -07:00
self.name = name
2015-05-30 00:36:54 -07:00
self.requires_network = bool(requires_network)
self.requires_wallet = bool(requires_wallet)
self.requires_password = bool(requires_password)
self.params = params
self.options = options
self.help = help
2013-10-03 03:39:42 -07:00
self.description = description
known_commands = {}
2013-10-03 03:39:42 -07:00
def register_command(*args):
global known_commands
name = args[0]
known_commands[name] = Command(*args)
2013-02-26 07:29:44 -08:00
2013-10-03 03:39:42 -07:00
# command
2015-05-30 00:36:54 -07:00
# requires_network
# requires_wallet
# requires_password
# arguments
# options
2015-05-30 07:14:56 -07:00
register_command('listcontacts', 0, 0, 0, [], [], 'Show your list of contacts', '')
register_command('create', 0, 1, 0, [], [], 'Create a new wallet', '')
register_command('createmultisig', 0, 1, 0, [('num','number'), ('pubkeys', 'Public keys (json)')], [], 'Create multisig address', '')
register_command('createrawtx', 0, 1, 0, [('inputs', ''), ('outputs', '')], [], 'Create an unsigned transaction.', 'The syntax is similar to bitcoind.')
register_command('deseed', 0, 1, 0, [], [], 'Remove seed from wallet.', 'This creates a seedless, watching-only wallet.')
register_command('decoderawtx', 0, 0, 0, [('tx', 'Serialized transaction')], [], 'Decode raw transaction.', '')
register_command('getprivatekeys', 0, 1, 1, [('address', 'Bitcoin address')], [], 'Get the private keys of a wallet address.', '')
register_command('dumpprivkeys', 0, 1, 1, [], [], 'Dump private keys from your wallet', '')
register_command('freeze', 0, 1, 1, [('address', 'Bitcoin address')], [], 'Freeze address.', 'Freeze the funds at one of your wallet\'s addresses')
register_command('getbalance', 1, 1, 0, [], [], 'Return the balance of your wallet', '')
register_command('getservers', 1, 0, 0, [], [], 'Return the list of available servers', '')
register_command('getaddressbalance', 1, 0, 0, [('address', 'Bitcoin address')], [], 'Return the balance of an address', '')
register_command('getaddresshistory', 1, 0, 0, [('address', 'Bitcoin address')], [], 'Return the transaction history of a wallet address', '')
register_command('getconfig', 0, 0, 0, [('key', 'Variable name')], [], 'Return a configuration variable', '')
register_command('getpubkeys', 0, 1, 0, [('address', 'Bitcoin address')], [], 'Return the public keys for a wallet address', '')
register_command('getrawtx', 1, 0, 0, [('txid', 'Transaction ID')], [], 'Retrieve a transaction', '')
register_command('getseed', 0, 1, 1, [], [], 'Get seed phrase', 'Print the generation seed of your wallet.')
register_command('getmpk', 0, 1, 0, [], [], 'Get Master Public Key', 'Return your wallet\'s master public key')
register_command('help', 0, 0, 0, [], [], 'Print help on a command.', '')
register_command('history', 1, 1, 0, [], [], 'Wallet history', 'Returns the transaction history of your wallet')
register_command('importprivkey', 0, 1, 1, [('privkey', 'Private key')], [], 'Import a private key', '')
register_command('ismine', 0, 1, 0, [('address', 'Bitcoin address')], [], 'Check if address is in wallet', 'Return true if and only if address is in wallet')
register_command('listaddresses', 0, 1, 0, [], ['show_all', 'show_labels'], 'List wallet addresses', 'Returns your list of addresses.')
register_command('listunspent', 1, 1, 0, [], [], 'List unspent outputs', 'Returns the list of unspent transaction outputs in your wallet.')
register_command('getaddressunspent', 1, 0, 0, [('address', 'Bitcoin address')], [], 'Returns the list of unspent inputs for an address.', '')
register_command('mktx', 0, 1, 1, [('recipient', 'Bitcoin address'), ('amount', 'Amount in BTC')],
['tx_fee', 'from_addr', 'change_addr'], 'Create signed transaction', '')
2015-05-30 07:14:56 -07:00
register_command('payto', 1, 1, 1, [('recipient', 'Bitcoin address'), ('amount', 'Amount in BTC')],
['tx_fee', 'from_addr', 'change_addr'], 'Create and broadcast a transaction.', '')
2015-05-30 07:14:56 -07:00
register_command('mktx_csv', 0, 1, 1, [('csv_file', 'CSV file of recipient, amount')], ['tx_fee', 'from_addr', 'change_addr'], 'Create a signed transaction', '')
register_command('payto_csv', 1, 1, 1, [('csv_file', '')], ['tx_fee', 'from_addr', 'change_addr'], 'Create and broadcast a transaction.', '')
register_command('password', 0, 1, 1, [], [], 'Change your password', '')
register_command('restore', 1, 1, 0, [], ['gap_limit', 'mpk', 'concealed'], 'Restore a wallet from seed', '')
register_command('searchcontacts', 0, 1, 0, [('query', '')], [], 'Search through contacts, return matching entries', '')
register_command('setconfig', 0, 0, 0, [('key', ''), ('value', '')], [], 'Set a configuration variable', '')
register_command('setlabel', 0, 1, 0, [('txid', 'Transaction ID'), ('label', '')], [], 'Assign a label to an item', '')
register_command('sendrawtx', 1, 0, 0, [('tx', 'Serialized transaction')], [], 'Broadcast a transaction to the network.', '')
register_command('signtxwithkey', 0, 0, 0, [('tx', 'raw_tx'), ('key', '')], [], 'Sign a serialized transaction with a key', '')
register_command('signtxwithwallet', 0, 1, 1, [('tx', 'raw_tx')], [], 'Sign a serialized transaction with a wallet', '')
register_command('signmessage', 0, 1, 1, [('address', 'Bitcoin address'), ('message', 'Message to sign.')], [],
'Sign a message with a key.', 'Use quotes if your message contains whitespaces')
2015-05-30 07:14:56 -07:00
register_command('unfreeze', 0, 1, 0, [('address', 'Bitcoin address')], [], 'Unfreeze the funds at one of your wallet\'s address', '')
register_command('validateaddress', 0, 0, 0, [('address', 'Bitcoin address')], [], 'Check that the address is valid', '')
register_command('verifymessage', 0, 0, 0, [('address', 'Bitcoin address'), ('signature', 'Signature'), ('message', 'Message')], [], 'Verify a signature', '')
register_command('version', 0, 0, 0, [], [], 'Return the version of your client', '')
register_command('encrypt', 0, 0, 0, [('pubkey', 'public key'), ('message', 'Message to encrypt.')], [],
'Encrypt a message with a public key.', 'Use quotes if the message contains whitespaces.')
2015-05-30 07:14:56 -07:00
register_command('decrypt', 0, 1, 1, [('pubkey', 'public key'), ('message', 'Encrypted message')], [], 'Decrypt a message encrypted with a public key', '')
register_command('getmerkle', 1, 0, 0, [('txid', 'Transaction ID'), ('height', 'Block height')], [], 'Get Merkle branch of a transaction included in a block', '')
register_command('getproof', 1, 0, 0, [('address', '')], [], 'Get Merkle branch of an address in the UTXO set', '')
register_command('getutxoaddress', 1, 0, 0, [('txid', 'Transction ID'), ('pos', 'Position')], [], 'Get the address of an unspent transaction output', '')
register_command('sweep', 1, 0, 0, [('privkey', 'Private key'), ('address', 'Destination address')], ['tx_fee'], 'Sweep a private key.', '')
register_command('make_seed', 0, 0, 0, [], ['nbits', 'entropy', 'language'], 'Create a seed.', '')
register_command('check_seed', 0, 0, 0, [('seed', 'Seed phrase')], ['entropy', 'language'], 'Check that a seed was generated with external entropy.', '')
command_options = {
'password': ("-W", "--password", None, "Password"),
'concealed': ("-C", "--concealed", False, "Don't echo seed to console when restoring"),
'show_all': ("-a", "--all", False, "Show all addresses"),
'show_labels': ("-l", "--labels", False, "Show the labels of listed addresses"),
2015-05-30 00:43:42 -07:00
'tx_fee': ("-f", "--fee", None, "Transaction fee"),
'from_addr': ("-F", "--fromaddr", None, "Source address. 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."),
'change_addr': ("-c", "--changeaddr", None, "Change address. Default is a spare address, or the source address if it's not in the wallet"),
'nbits': (None, "--nbits", "128", "Number of bits of entropy"),
'entropy': (None, "--entropy", "1", "Custom entropy"),
'language': ("-L", "--lang", None, "Default language for wordlist"),
'gap_limit': ("-G", "--gap", None, "Gap limit"),
'mpk': (None, "--mpk", None, "Restore from master public key"),
}
def set_default_subparser(self, name, args=None):
"""see http://stackoverflow.com/questions/5176691/argparse-how-to-specify-a-default-subcommand"""
subparser_found = False
for arg in sys.argv[1:]:
if arg in ['-h', '--help']: # global help if no subparser
break
else:
for x in self._subparsers._actions:
if not isinstance(x, argparse._SubParsersAction):
continue
for sp_name in x._name_parser_map.keys():
if sp_name in sys.argv[1:]:
subparser_found = True
if not subparser_found:
# insert default in first position, this implies no
# global options without a sub_parsers specified
if args is None:
sys.argv.insert(1, name)
else:
args.insert(0, name)
argparse.ArgumentParser.set_default_subparser = set_default_subparser
2015-05-30 04:38:05 -07:00
def add_network_options(parser):
parser.add_argument("-1", "--oneserver", action="store_true", dest="oneserver", default=False, help="connect to one server only")
parser.add_argument("-s", "--server", dest="server", default=None, help="set server host:port:protocol, where protocol is either t (tcp) or s (ssl)")
parser.add_argument("-p", "--proxy", dest="proxy", default=None, help="set proxy [type:]host[:port], where type is socks4,socks5 or http")
def get_parser(run_gui, run_daemon, run_cmdline):
# parent parser, because set_default_subparser removes global options
parent_parser = argparse.ArgumentParser('parent', add_help=False)
parent_parser.add_argument("-v", "--verbose", action="store_true", dest="verbose", default=False, help="Show debugging information")
2015-05-30 04:38:05 -07:00
parent_parser.add_argument("-P", "--portable", action="store_true", dest="portable", default=False, help="Use local 'electrum_data' directory")
# create main parser
2015-05-30 04:38:05 -07:00
parser = argparse.ArgumentParser(
parents=[parent_parser],
epilog="Run 'electrum help <command>' to see the help for a command")
subparsers = parser.add_subparsers(dest='cmd', metavar='<command>')
# gui
parser_gui = subparsers.add_parser('gui', parents=[parent_parser], description="Run Electrum's Graphical User Interface.", help="Run GUI (default)")
parser_gui.add_argument("url", nargs='?', default=None, help="bitcoin URI (or bip70 file)")
parser_gui.set_defaults(func=run_gui)
parser_gui.add_argument("-g", "--gui", dest="gui", help="select graphical user interface", choices=['qt', 'lite', 'gtk', 'text', 'stdio'])
parser_gui.add_argument("-m", action="store_true", dest="hide_gui", default=False, help="hide GUI on startup")
2015-05-29 21:38:46 -07:00
parser_gui.add_argument("-L", "--lang", dest="language", default=None, help="default language used in GUI")
2015-05-30 04:38:05 -07:00
parser_gui.add_argument("-o", "--offline", action="store_true", dest="offline", default=False, help="Run the GUI offline")
parser_gui.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
add_network_options(parser_gui)
# daemon
parser_daemon = subparsers.add_parser('daemon', parents=[parent_parser], help="Run Daemon")
parser_daemon.add_argument("subcommand", choices=['start', 'status', 'stop'])
parser_daemon.set_defaults(func=run_daemon)
2015-05-30 04:38:05 -07:00
add_network_options(parser_daemon)
# commands
for cmdname in sorted(known_commands.keys()):
cmd = known_commands[cmdname]
p = subparsers.add_parser(cmdname, parents=[parent_parser], help=cmd.help, description=cmd.help + ' ' + cmd.description)
p.set_defaults(func=run_cmdline)
if cmd.requires_password:
p.add_argument("-W", "--password", dest="password", default=None, help="password")
2015-05-30 04:38:05 -07:00
if cmd.requires_network:
p.add_argument("-o", "--offline", action="store_true", dest="offline", default=False, help="Run command offline")
if cmd.requires_wallet:
p.add_argument("-w", "--wallet", dest="wallet_path", help="wallet path")
for optname in cmd.options:
a, b, default, help = command_options[optname]
action = "store_true" if type(default) is bool else 'store'
args = (a, b) if a else (b,)
p.add_argument(*args, dest=optname, action=action, default=default, help=help)
2015-05-30 07:14:56 -07:00
for param, h in cmd.params:
2015-05-30 00:36:54 -07:00
p.add_argument(param, help=h)
2015-05-30 04:38:05 -07:00
# 'gui' is the default command
parser.set_default_subparser('gui')
return parser
2014-01-26 11:46:43 -08:00
class Commands:
2015-05-30 03:35:58 -07:00
def __init__(self, config, wallet, network, callback = None):
self.config = config
self.wallet = wallet
2013-09-15 02:19:48 -07:00
self.network = network
2013-02-27 03:40:16 -08:00
self._callback = callback
2013-03-13 06:29:50 -07:00
self.password = None
def _run(self, method, args, password_getter):
2013-10-03 03:39:42 -07:00
cmd = known_commands[method]
if cmd.requires_password and self.wallet.use_encryption:
self.password = apply(password_getter,())
2013-11-11 22:03:20 -08:00
f = getattr(self, method)
result = f(*args)
self.password = None
2013-02-27 03:40:16 -08:00
if self._callback:
apply(self._callback, ())
return result
def make_seed(self, nbits, custom_entropy, language):
from mnemonic import Mnemonic
2014-09-09 02:51:45 -07:00
s = Mnemonic(language).make_seed(nbits, custom_entropy=custom_entropy)
2014-09-03 08:21:43 -07:00
return s.encode('utf8')
def check_seed(self, seed, custom_entropy, language):
from mnemonic import Mnemonic
return Mnemonic(language).check_seed(seed, custom_entropy)
def getaddresshistory(self, addr):
2014-01-23 08:06:47 -08:00
return self.network.synchronous_get([ ('blockchain.address.get_history',[addr]) ])[0]
def listunspent(self):
2015-05-05 22:25:50 -07:00
l = copy.deepcopy(self.wallet.get_spendable_coins())
2013-02-28 21:43:08 -08:00
for i in l: i["value"] = str(Decimal(i["value"])/100000000)
return l
2014-01-23 08:06:47 -08:00
def getaddressunspent(self, addr):
2014-01-26 11:46:43 -08:00
return self.network.synchronous_get([ ('blockchain.address.listunspent',[addr]) ])[0]
2014-01-23 08:06:47 -08:00
2014-03-02 02:02:45 -08:00
def getutxoaddress(self, txid, num):
r = self.network.synchronous_get([ ('blockchain.utxo.get_address',[txid, num]) ])
if r:
2014-03-02 02:02:45 -08:00
return {'address':r[0] }
2014-01-30 06:16:49 -08:00
def createrawtransaction(self, inputs, outputs):
2015-05-05 22:25:50 -07:00
coins = self.wallet.get_spendable_coins(None)
tx_inputs = []
for i in inputs:
prevout_hash = i['txid']
prevout_n = i['vout']
for c in coins:
if c['prevout_hash'] == prevout_hash and c['prevout_n'] == prevout_n:
self.wallet.add_input_info(c)
tx_inputs.append(c)
break
else:
raise BaseException('Transaction output not in wallet', prevout_hash+":%d"%prevout_n)
outputs = map(lambda x: ('address', x[0], int(1e8*x[1])), outputs.items())
tx = Transaction.from_io(tx_inputs, outputs)
2013-09-14 12:53:56 -07:00
return tx
def signtxwithkey(self, raw_tx, sec):
tx = Transaction(raw_tx)
pubkey = bitcoin.public_key_from_private_key(sec)
tx.sign({ pubkey:sec })
return tx
def signtxwithwallet(self, raw_tx):
tx = Transaction(raw_tx)
tx.deserialize()
self.wallet.sign_transaction(tx, self.password)
2013-09-14 12:53:56 -07:00
return tx
def decoderawtransaction(self, raw):
tx = Transaction(raw)
tx.deserialize()
return {'inputs':tx.inputs, 'outputs':tx.outputs}
def sendrawtransaction(self, raw):
tx = Transaction(raw)
2013-12-21 09:29:09 -08:00
return self.network.synchronous_get([('blockchain.transaction.broadcast', [str(tx)])])[0]
def createmultisig(self, num, pubkeys):
assert isinstance(pubkeys, list)
2013-08-17 00:53:46 -07:00
redeem_script = Transaction.multisig_script(pubkeys, num)
address = hash_160_to_bc_address(hash_160(redeem_script.decode('hex')), 5)
return {'address':address, 'redeemScript':redeem_script}
def freeze(self,addr):
return self.wallet.freeze(addr)
def unfreeze(self,addr):
return self.wallet.unfreeze(addr)
def getprivatekeys(self, addr):
return self.wallet.get_private_key(addr, self.password)
def ismine(self, addr):
return self.wallet.is_mine(addr)
2013-02-27 01:36:52 -08:00
def dumpprivkeys(self, addresses = None):
if addresses is None:
addresses = self.wallet.addresses(True)
2013-09-10 13:07:09 -07:00
return [self.wallet.get_private_key(address, self.password) for address in addresses]
2013-10-03 04:31:59 -07:00
def validateaddress(self, addr):
isvalid = is_valid(addr)
out = { 'isvalid':isvalid }
if isvalid:
out['address'] = addr
2013-11-04 03:41:43 -08:00
return out
2013-10-03 04:31:59 -07:00
def getpubkeys(self, addr):
out = { 'address':addr }
2014-07-06 13:24:09 -07:00
out['pubkeys'] = self.wallet.get_public_keys(addr)
return out
def getbalance(self, account= None):
if account is None:
c, u, x = self.wallet.get_balance()
else:
c, u, x = self.wallet.get_account_balance(account)
out = {"confirmed": str(Decimal(c)/100000000)}
if u:
out["unconfirmed"] = str(Decimal(u)/100000000)
if x:
out["unmatured"] = str(Decimal(x)/100000000)
return out
2013-02-27 01:24:53 -08:00
def getaddressbalance(self, addr):
out = self.network.synchronous_get([ ('blockchain.address.get_balance',[addr]) ])[0]
out["confirmed"] = str(Decimal(out["confirmed"])/100000000)
out["unconfirmed"] = str(Decimal(out["unconfirmed"])/100000000)
return out
2014-01-29 07:48:24 -08:00
def getproof(self, addr):
p = self.network.synchronous_get([ ('blockchain.address.get_proof',[addr]) ])[0]
out = []
for i,s in p:
out.append(i)
return out
2015-05-12 03:30:26 -07:00
def getmerkle(self, txid, height):
return self.network.synchronous_get([ ('blockchain.transaction.get_merkle', [txid, int(height)]) ])[0]
def getservers(self):
while not self.network.is_up_to_date():
time.sleep(0.1)
return self.network.get_servers()
def version(self):
import electrum # Needs to stay here to prevent ciruclar imports
2013-12-01 00:42:22 -08:00
return electrum.ELECTRUM_VERSION
def getmpk(self):
2014-06-21 23:06:37 -07:00
return self.wallet.get_master_public_keys()
2013-03-01 02:25:50 -08:00
def getseed(self):
2014-09-03 09:52:43 -07:00
s = self.wallet.get_mnemonic(self.password)
return s.encode('utf8')
def importprivkey(self, sec):
try:
2013-03-06 03:32:11 -08:00
addr = self.wallet.import_key(sec,self.password)
2013-02-27 01:24:53 -08:00
out = "Keypair imported: ", addr
2013-11-09 20:21:02 -08:00
except Exception as e:
2013-02-27 01:24:53 -08:00
out = "Error: Keypair import failed: " + str(e)
return out
2014-04-25 08:23:26 -07:00
def sweep(self, privkey, to_address, fee = 0.0001):
2014-05-01 08:35:01 -07:00
fee = int(Decimal(fee)*100000000)
return Transaction.sweep([privkey], self.network, to_address, fee)
2014-04-25 08:23:26 -07:00
2013-03-01 02:25:50 -08:00
def signmessage(self, address, message):
return self.wallet.sign_message(address, message, self.password)
2013-03-01 02:25:50 -08:00
def verifymessage(self, address, signature, message):
return bitcoin.verify_message(address, signature, message)
def _mktx(self, outputs, fee = None, change_addr = None, domain = None):
for to_address, amount in outputs:
if not is_valid(to_address):
2013-11-09 20:21:02 -08:00
raise Exception("Invalid Bitcoin address", to_address)
if change_addr:
if not is_valid(change_addr):
2013-11-09 20:21:02 -08:00
raise Exception("Invalid Bitcoin address", change_addr)
if domain is not None:
for addr in domain:
if not is_valid(addr):
2013-11-09 20:21:02 -08:00
raise Exception("invalid Bitcoin address", addr)
if not self.wallet.is_mine(addr):
2013-11-09 20:21:02 -08:00
raise Exception("address not in wallet", addr)
for k, v in self.wallet.labels.items():
if change_addr and v == change_addr:
change_addr = k
final_outputs = []
for to_address, amount in outputs:
for k, v in self.wallet.labels.items():
if v == to_address:
to_address = k
print_msg("alias", to_address)
break
amount = int(100000000*amount)
2014-07-08 10:38:16 -07:00
final_outputs.append(('address', to_address, amount))
2015-03-14 08:22:47 -07:00
if fee is not None: fee = int(100000000*fee)
return self.wallet.mktx(final_outputs, self.password, fee , change_addr, domain)
2013-02-26 06:13:01 -08:00
def mktx(self, to_address, amount, fee = None, change_addr = None, domain = None):
tx = self._mktx([(to_address, amount)], fee, change_addr, domain)
2013-09-14 12:07:54 -07:00
return tx
2015-05-29 10:23:49 -07:00
def _read_csv(self, csvpath):
import csv
outputs = []
with open(csvpath, 'rb') as csvfile:
csvReader = csv.reader(csvfile, delimiter=',')
for row in csvReader:
address, amount = row
assert bitcoin.is_address(address)
amount = Decimal(amount)
outputs.append((address, amount))
return outputs
def mktx_csv(self, path, fee = None, change_addr = None, domain = None):
outputs = self._read_csv(path)
tx = self._mktx(outputs, fee, change_addr, domain)
2013-09-14 12:53:56 -07:00
return tx
def payto(self, to_address, amount, fee = None, change_addr = None, domain = None):
tx = self._mktx([(to_address, amount)], fee, change_addr, domain)
r, h = self.wallet.sendtx( tx )
return h
2015-05-29 10:23:49 -07:00
def payto_csv(self, path, fee = None, change_addr = None, domain = None):
outputs = self._read_csv(path)
tx = self._mktx(outputs, fee, change_addr, domain)
r, h = self.wallet.sendtx( tx )
return h
def history(self):
balance = 0
2013-02-26 09:10:29 -08:00
out = []
for item in self.wallet.get_history():
2015-04-27 23:58:33 -07:00
tx_hash, conf, value, timestamp, balance = item
try:
time_str = datetime.datetime.fromtimestamp( timestamp).isoformat(' ')[:-3]
2013-11-09 21:23:57 -08:00
except Exception:
time_str = "----"
label, is_default_label = self.wallet.get_label(tx_hash)
out.append({'txid':tx_hash, 'date':"%16s"%time_str, 'label':label, 'value':format_satoshis(value), 'confirmations':conf})
2013-02-26 09:10:29 -08:00
return out
2013-09-08 11:10:43 -07:00
def setlabel(self, key, label):
2013-09-08 11:12:03 -07:00
self.wallet.set_label(key, label)
2013-09-08 11:10:43 -07:00
2015-05-30 03:35:58 -07:00
def listcontacts(self):
contacts = StoreDict(self.config, 'contacts')
return contacts
2014-11-05 15:02:44 -08:00
def searchcontacts(self, query):
2015-05-30 03:35:58 -07:00
contacts = StoreDict(self.config, 'contacts')
2014-11-05 15:02:44 -08:00
results = {}
2015-05-30 03:35:58 -07:00
for key, value in contacts.items():
if query.lower() in key.lower():
results[key] = value
2014-11-05 15:02:44 -08:00
return results
def listaddresses(self, show_all = False, show_label = False):
2013-02-26 09:10:29 -08:00
out = []
for addr in self.wallet.addresses(True):
2013-02-26 07:11:19 -08:00
if show_all or not self.wallet.is_change(addr):
if show_label:
item = { 'address': addr }
if show_label:
label = self.wallet.labels.get(addr,'')
if label:
item['label'] = label
else:
item = addr
out.append( item )
2013-02-26 09:10:29 -08:00
return out
2014-01-13 12:27:31 -08:00
def getrawtransaction(self, tx_hash):
if self.wallet:
tx = self.wallet.transactions.get(tx_hash)
if tx:
return tx
2014-01-23 08:06:47 -08:00
raw = self.network.synchronous_get([ ('blockchain.transaction.get',[tx_hash]) ])[0]
if raw:
return Transaction(raw)
2014-01-23 08:06:47 -08:00
else:
return "unknown transaction"
def encrypt(self, pubkey, message):
2014-03-03 01:39:10 -08:00
return bitcoin.encrypt_message(message, pubkey)
2014-03-11 06:11:45 -07:00
def decrypt(self, pubkey, message):
return self.wallet.decrypt_message(pubkey, message, self.password)