diff --git a/pybitcoin/services/__init__.py b/pybitcoin/services/__init__.py index c23214e..b7d92ff 100644 --- a/pybitcoin/services/__init__.py +++ b/pybitcoin/services/__init__.py @@ -12,6 +12,7 @@ from blockchain_info import BlockchainInfoClient from chain_com import ChainComClient from bitcoind import BitcoindClient, create_bitcoind_service_proxy +from electrum_client import ElectrumClient import blockcypher import blockchain_info diff --git a/pybitcoin/services/electrum_client.py b/pybitcoin/services/electrum_client.py new file mode 100644 index 0000000..1883b1f --- /dev/null +++ b/pybitcoin/services/electrum_client.py @@ -0,0 +1,52 @@ +""" +Electrum client for pybitcoin +""" + +import jsonrpclib + +from ..transactions.serialize import deserialize_transaction + + +class ElectrumClient(): + """ + Electrum Blockchain interface class + """ + def __init__(self, api_endpoint): + self.api_endpoint = api_endpoint + self.electrum = jsonrpclib.Server(self.api_endpoint) + + def _format_unspents(self, unspents): + """ + Make electrum's output consumable by pybitcoin. + """ + # FIXME: This is off-by-one and behavior for unconfirmed is unknown, + # will leave out for now. + # daemon_status = self.electrum.daemon({'subcommand': 'status'}) + # blockchain_height = daemon_status['blockchain_height'] + formatted_unspents = [] + for unspent in unspents: + tx_hash = unspent['tx_hash'] + transaction = self.electrum.gettransaction(tx_hash)['hex'] + deserialized_tx = deserialize_transaction(transaction) + script_hex = deserialized_tx[1][0]['script_hex'] + # confirmations = blockchain_height - unspent['height'] + confirmations = 0 + # electrum's tx_hash is the big endian version already. + formatted_unspent = {'transaction_hash': unspent['tx_hash'], + 'output_index': unspent['tx_pos'], + 'value': unspent['value'], + 'script_hex': script_hex, + 'confirmations': confirmations} + formatted_unspents.append(formatted_unspent) + return formatted_unspents + + def get_unspents(self, address): + unspents = self.electrum.getaddressunspent(address) + return self._format_unspents(unspents) + + def broadcast_transaction(self, tx): + broadcast_output = self.electrum.broadcast(tx) + if broadcast_output[0] is False: + raise Exception(str(broadcast_output)) + else: + return broadcast_output diff --git a/requirements.txt b/requirements.txt index 196627d..56cb878 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ utilitybelt>=0.2.1 python-bitcoinrpc==0.1 keychain>=0.1.4 bitcoin>=1.1.42 +jsonrpclib-pelix diff --git a/setup.py b/setup.py index 68302d1..354cf7d 100755 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name='pybitcoin', - version='0.9.9', + version='0.9.10', url='https://github.com/blockstack/pybitcoin', license='MIT', author='Blockstack Developers', @@ -25,7 +25,8 @@ 'utilitybelt>=0.2.6', 'python-bitcoinrpc==0.1', 'keychain>=0.1.4', - 'bitcoin>=1.1.42' + 'bitcoin>=1.1.42', + 'jsonrpclib-pelix' ], classifiers=[ 'Intended Audience :: Developers',