class Wallet(QtCore.QObject): balanceUpdated = QtCore.pyqtSignal(name='balanceUpdated') def __init__(self, dataDir, isTestNet): QtCore.QObject.__init__(self) self.lock = threading.Lock() self._patching_BaseTxDb() self.wallet_path = os.path.join(dataDir, 'wallet.sqlite') self._pwallet = PersistentWallet(self.wallet_path, isTestNet) self._set_wallet_settings(dataDir, isTestNet) self._pwallet.init_model() self._wallet = self._pwallet.get_model() self._controller = WalletController(self._wallet) self._utxo_fetcher = AsyncUTXOFetcher( self._wallet, self._pwallet.wallet_config.get('utxo_fetcher', {})) self._utxo_fetcher_timer = QtCore.QTimer() self._utxo_fetcher_timer.timeout.connect(self._utxo_fetcher.update) self._utxo_fetcher_timer.setInterval(1000) asset = self.get_asset_definition('bitcoin') if len(self._controller.get_all_addresses(asset)) == 0: self._controller.get_new_address(asset) self._create_club_asset() def _patching_BaseTxDb(self): original_add_tx = BaseTxDb.add_tx def new_add_tx(baseTxDb, txhash, txdata, raw_tx, *args, **kwargs): retval = original_add_tx(baseTxDb, txhash, txdata, raw_tx, *args, **kwargs) if retval: ctxs = raw_tx.composed_tx_spec coinStore = self._wallet.get_coin_manager().store all_addresses = [ a.get_address() for a in self._wallet.get_address_manager().get_all_addresses() ] lookup_moniker_by_address = {} for asset in self._controller.get_all_assets(): monikers = asset.get_monikers() for address in self._controller.get_all_addresses(asset): lookup_moniker_by_address[ address.get_address()] = monikers # txin for txin in ctxs.txins: prev_txhash, prev_outindex = txin.get_outpoint() coin_id = coinStore.find_coin(prev_txhash, prev_outindex) if coin_id: address = coinStore.get_coin(coin_id)['address'] self.balanceUpdated.emit() # txout for txout in ctxs.txouts: target_addr = txout.target_addr if target_addr in all_addresses: self.balanceUpdated.emit() return retval BaseTxDb.add_tx = new_add_tx def _set_wallet_settings(self, dataDir, isTestNet): self._pwallet.wallet_config['testnet'] = isTestNet ccc = self._pwallet.wallet_config.get('ccc', {}) ccc['colordb_path'] = os.path.join(dataDir, 'color_db.sqlite') self._pwallet.wallet_config['ccc'] = ccc def _create_club_asset(self): for asset in self._wallet.get_asset_definition_manager( ).get_all_assets(): for color in asset.get_color_set().get_data(): if color in clubAsset['color_set']: return self._wallet.get_asset_definition_manager().add_asset_definition( clubAsset) asset = self.get_asset_definition(clubAsset['monikers'][0]) if len(self._controller.get_all_addresses(asset)) == 0: self._controller.get_new_address(asset).get_color_address() def sync_start(self): self._utxo_fetcher.start_thread() self._utxo_fetcher_timer.start() def sync_stop(self): self._utxo_fetcher.stop() self._utxo_fetcher_timer.stop() def get_asset_definition(self, moniker): if isinstance(moniker, AssetDefinition): return moniker adm = self._wallet.get_asset_definition_manager() asset = adm.get_asset_by_moniker(moniker) if not asset: raise Exception("asset not found") return asset def get_address(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_all_addresses(asset)[0].get_color_address() def get_bitcoin_address(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_all_addresses(asset)[0].get_address() def get_total_balance(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_total_balance(asset) def get_available_balance(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_available_balance(asset) def get_unconfirmed_balance(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_unconfirmed_balance(asset) def send_coins(self, moniker, address): asset = self.get_asset_definition(moniker) total = self.get_total_balance(asset) self._controller.send_coins(asset, [address], [total]) def get_auth_data(self, moniker): with self.lock: coin = self._wallet.make_coin_query({ 'asset': self.get_asset_definition(moniker), 'spent': False, }).get_result()[0] pubKey = public_pair_to_sec(coin.address_rec.publicPoint.pair(), compressed=False) return { 'color_set': clubAsset['color_set'][0], 'txhash': coin.txhash, 'outindex': coin.outindex, 'pubkey': pubKey.encode('hex'), 'privkey': coin.address_rec.rawPrivKey, 'address_rec': coin.address_rec, } def sign_data(self, data, privKey): with self.lock: symbols_set = string.ascii_letters + string.digits salt = ''.join([random.choice(symbols_set) for _ in xrange(20)]) data = int((hash160(str(data) + salt)).encode('hex'), 16) return { 'salt': salt, 'sign': ecdsa.sign(ecdsa.generator_secp256k1, privKey, data), } def validate_bitcoin_address(self, address): bcbytes = a2b_base58(str(address)) return bcbytes[-4:] == sha256(sha256( bcbytes[:-4]).digest()).digest()[:4]
class Wallet(object): thread_comm = None def __init__(self): parser = argparse.ArgumentParser() parser.add_argument("--wallet", dest="wallet_path") parser.add_argument("--testnet", action='store_true') parsed_args = vars(parser.parse_args()) self.wallet = PersistentWallet(parsed_args.get('wallet_path'), parsed_args.get('testnet')) self.wallet.init_model() self.model = self.wallet.get_model() self.controller = WalletController(self.wallet.get_model()) self.async_utxo_fetcher = AsyncUTXOFetcher( self.model, self.wallet.wallet_config.get('utxo_fetcher', {})) def get_asset_definition(self, moniker): if isinstance(moniker, AssetDefinition): return moniker adm = self.wallet.get_model().get_asset_definition_manager() asset = adm.get_asset_by_moniker(moniker) if asset: return asset else: raise Exception("asset not found") def get_asset_definition_by_color_set(self, color_set): adm = self.wallet.get_model().get_asset_definition_manager() for asset in adm.get_all_assets(): if color_set in asset.get_color_set().get_data(): return asset raise Exception("asset not found") def add_asset(self, params): self.controller.add_asset_definition({ "monikers": [params['moniker']], "color_set": [params['color_desc']], "unit": params['unit'] }) if len(self.get_all_addresses(params['moniker'])) == 0: self.get_new_address(params['moniker']) def get_all_asset(self): return self.wallet.wallet_config['asset_definitions'] def issue(self, params): self.controller.issue_coins( params['moniker'], params['coloring_scheme'], params['units'], params['atoms']) if len(self.get_all_addresses(params['moniker'])) == 0: self.get_new_address(params['moniker']) def get_all_monikers(self): monikers = [asset.get_monikers()[0] for asset in self.model.get_asset_definition_manager().get_all_assets()] monikers.remove('bitcoin') monikers = ['bitcoin'] + monikers return monikers def get_available_balance(self, color): return self.controller.get_available_balance( self.get_asset_definition(color)) def get_total_balance(self, color): return self.controller.get_total_balance( self.get_asset_definition(color)) def get_unconfirmed_balance(self, color): return self.controller.get_unconfirmed_balance( self.get_asset_definition(color)) def get_all_addresses(self, color): return [addr.get_color_address() for addr in self.controller.get_all_addresses(self.get_asset_definition(color))] def get_received_by_address(self, color): asset = self.get_asset_definition(color) return self.controller.get_received_by_address(asset) def get_some_address(self, color): wam = self.model.get_address_manager() cs = self.get_asset_definition(color).get_color_set() ar = wam.get_some_address(cs) return ar.get_color_address() def get_new_address(self, color): return self.controller. \ get_new_address(self.get_asset_definition(color)).get_color_address() def scan(self): self.controller.scan_utxos() def send_coins(self, items): if isinstance(items, dict): items = [items] for item in items: self.controller.send_coins( item['asset'] if 'asset' in item \ else self.get_asset_definition(item['moniker']), [item['address']], [item['value']]) def p2ptrade_init(self): ewctrl = EWalletController(self.model, self.controller) config = {"offer_expiry_interval": 30, "ep_expiry_interval": 30} comm = HTTPComm( config, 'http://p2ptrade.btx.udoidio.info/messages') self.thread_comm = ThreadedComm(comm) self.p2p_agent = EAgent(ewctrl, config, self.thread_comm) self.thread_comm.start() def p2ptrade_stop(self): if self.thread_comm is not None: self.thread_comm.stop() def p2ptrade_make_offer(self, we_sell, params): asset = self.get_asset_definition(params['moniker']) value = asset.parse_value(params['value']) bitcoin = self.get_asset_definition('bitcoin') price = bitcoin.parse_value(params['price']) total = int(float(value)/float(asset.unit)*float(price)) color_desc = asset.get_color_set().color_desc_list[0] sell_side = {"color_spec": color_desc, "value": value} buy_side = {"color_spec": "", "value": total} if we_sell: return MyEOffer(None, sell_side, buy_side) else: return MyEOffer(None, buy_side, sell_side) def p2ptrade_make_mirror_offer(self, offer): data = offer.get_data() return MyEOffer(None, data['B'], data['A'], False) def stop_all(self): self.async_utxo_fetcher.stop() self.p2ptrade_stop() if hasattr(self.model.txdb, 'vbs'): self.model.txdb.vbs.stop()
class Wallet(QtCore.QObject): balanceUpdated = QtCore.pyqtSignal(name='balanceUpdated') def __init__(self, dataDir, isTestNet): QtCore.QObject.__init__(self) self.lock = threading.Lock() self._patching_BaseTxDb() self.wallet_path = os.path.join(dataDir, 'wallet.sqlite') self._pwallet = PersistentWallet(self.wallet_path, isTestNet) self._set_wallet_settings(dataDir, isTestNet) self._pwallet.init_model() self._wallet = self._pwallet.get_model() self._controller = WalletController(self._wallet) self._utxo_fetcher = AsyncUTXOFetcher( self._wallet, self._pwallet.wallet_config.get('utxo_fetcher', {})) self._utxo_fetcher_timer = QtCore.QTimer() self._utxo_fetcher_timer.timeout.connect(self._utxo_fetcher.update) self._utxo_fetcher_timer.setInterval(1000) asset = self.get_asset_definition('bitcoin') if len(self._controller.get_all_addresses(asset)) == 0: self._controller.get_new_address(asset) self._create_club_asset() def _patching_BaseTxDb(self): original_add_tx = BaseTxDb.add_tx def new_add_tx(baseTxDb, txhash, txdata, raw_tx, *args, **kwargs): retval = original_add_tx(baseTxDb, txhash, txdata, raw_tx, *args, **kwargs) if retval: ctxs = raw_tx.composed_tx_spec coinStore = self._wallet.get_coin_manager().store all_addresses = [a.get_address() for a in self._wallet.get_address_manager().get_all_addresses()] lookup_moniker_by_address = {} for asset in self._controller.get_all_assets(): monikers = asset.get_monikers() for address in self._controller.get_all_addresses(asset): lookup_moniker_by_address[address.get_address()] = monikers # txin for txin in ctxs.txins: prev_txhash, prev_outindex = txin.get_outpoint() coin_id = coinStore.find_coin(prev_txhash, prev_outindex) if coin_id: address = coinStore.get_coin(coin_id)['address'] self.balanceUpdated.emit() # txout for txout in ctxs.txouts: target_addr = txout.target_addr if target_addr in all_addresses: self.balanceUpdated.emit() return retval BaseTxDb.add_tx = new_add_tx def _set_wallet_settings(self, dataDir, isTestNet): self._pwallet.wallet_config['testnet'] = isTestNet ccc = self._pwallet.wallet_config.get('ccc', {}) ccc['colordb_path'] = os.path.join(dataDir, 'color_db.sqlite') self._pwallet.wallet_config['ccc'] = ccc def _create_club_asset(self): for asset in self._wallet.get_asset_definition_manager().get_all_assets(): for color in asset.get_color_set().get_data(): if color in clubAsset['color_set']: return self._wallet.get_asset_definition_manager().add_asset_definition(clubAsset) asset = self.get_asset_definition(clubAsset['monikers'][0]) if len(self._controller.get_all_addresses(asset)) == 0: self._controller.get_new_address(asset).get_color_address() def sync_start(self): self._utxo_fetcher.start_thread() self._utxo_fetcher_timer.start() def sync_stop(self): self._utxo_fetcher.stop() self._utxo_fetcher_timer.stop() def get_asset_definition(self, moniker): if isinstance(moniker, AssetDefinition): return moniker adm = self._wallet.get_asset_definition_manager() asset = adm.get_asset_by_moniker(moniker) if not asset: raise Exception("asset not found") return asset def get_address(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_all_addresses(asset)[0].get_color_address() def get_bitcoin_address(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_all_addresses(asset)[0].get_address() def get_total_balance(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_total_balance(asset) def get_available_balance(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_available_balance(asset) def get_unconfirmed_balance(self, moniker): asset = self.get_asset_definition(moniker) return self._controller.get_unconfirmed_balance(asset) def send_coins(self, moniker, address): asset = self.get_asset_definition(moniker) total = self.get_total_balance(asset) self._controller.send_coins(asset, [address], [total]) def get_auth_data(self, moniker): with self.lock: coin = self._wallet.make_coin_query({ 'asset': self.get_asset_definition(moniker), 'spent': False, }).get_result()[0] pubKey = public_pair_to_sec(coin.address_rec.publicPoint.pair(), compressed=False) return { 'color_set': clubAsset['color_set'][0], 'txhash': coin.txhash, 'outindex': coin.outindex, 'pubkey': pubKey.encode('hex'), 'privkey': coin.address_rec.rawPrivKey, 'address_rec': coin.address_rec, } def sign_data(self, data, privKey): with self.lock: symbols_set = string.ascii_letters + string.digits salt = ''.join([random.choice(symbols_set) for _ in xrange(20)]) data = int((hash160(str(data) + salt)).encode('hex'), 16) return { 'salt': salt, 'sign': ecdsa.sign(ecdsa.generator_secp256k1, privKey, data), } def validate_bitcoin_address(self, address): bcbytes = a2b_base58(str(address)) return bcbytes[-4:] == sha256(sha256(bcbytes[:-4]).digest()).digest()[:4]