lbry-sdk/lbrynet/wallet/manager.py
2018-08-24 11:37:25 -04:00

88 lines
2.9 KiB
Python

import os
import logging
from twisted.internet import defer
import lbryschema
from .protocol import Network
from .blockchain import BlockchainHeaders
from .wallet import Wallet
log = logging.getLogger(__name__)
def chunks(l, n):
for i in range(0, len(l), n):
yield l[i:i+n]
class WalletManager:
def __init__(self, storage, config):
self.storage = storage
self.config = config
lbryschema.BLOCKCHAIN_NAME = config['chain']
self.headers = BlockchainHeaders(self.headers_path, config['chain'])
self.wallet = Wallet(self.wallet_path)
self.network = Network(config)
self.network.on_header.listen(self.process_header)
self.network.on_transaction.listen(self.process_transaction)
self._downloading_headers = False
@property
def headers_path(self):
filename = 'blockchain_headers'
if self.config['chain'] != 'lbrycrd_main':
filename = '{}_headers'.format(self.config['chain'].split("_")[1])
return os.path.join(self.config['wallet_path'], filename)
@property
def wallet_path(self):
return os.path.join(self.config['wallet_path'], 'wallets', 'default_wallet')
@defer.inlineCallbacks
def start(self):
self.wallet.load()
self.network.start()
yield self.network.on_connected.first
yield self.download_headers()
yield self.network.headers_subscribe()
yield self.download_transactions()
def stop(self):
return self.network.stop()
@defer.inlineCallbacks
def download_headers(self):
self._downloading_headers = True
while True:
sought_height = len(self.headers)
headers = yield self.network.block_headers(sought_height)
log.info("received {} headers starting at {} height".format(headers['count'], sought_height))
if headers['count'] <= 0:
break
yield self.headers.connect(sought_height, headers['hex'].decode('hex'))
self._downloading_headers = False
@defer.inlineCallbacks
def process_header(self, header):
if self._downloading_headers:
return
if header['block_height'] == len(self.headers):
# New header from network directly connects after the last local header.
yield self.headers.connect(len(self.headers), header['hex'].decode('hex'))
elif header['block_height'] > len(self.headers):
# New header is several heights ahead of local, do download instead.
yield self.download_headers()
@defer.inlineCallbacks
def download_transactions(self):
for addresses in chunks(self.wallet.addresses, 500):
self.network.rpc([
('blockchain.address.subscribe', [address])
for address in addresses
])
def process_transaction(self, tx):
pass