forked from LBRYCommunity/lbry-sdk
88 lines
2.9 KiB
Python
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
|