def after_update(mapper, connection, alias): from app.models import Profile with profile_session_scope() as session: profile = Profile.get_active(session) if alias.address == profile.address: profile.alias = alias.alias signals.alias_list_changed.emit()
def setting_changed_manage_node(self, state): self.profile.manage_node = state == 2 with profile_session_scope() as session: session.add(self.profile) if self.profile.manage_node: self.node.start()
def init_data_db(): fp = '' with profile_session_scope() as session: profile_obj = Profile.get_active(session) if profile_obj is None: raise RuntimeError('cannot init data db without active profile') fp = profile_obj.data_db_filepath log.debug('init data db at: {}'.format(fp)) engine = sqlalchemy.create_engine('sqlite:///{}'.format(fp)) data_db.configure(bind=engine) engine.execute("PRAGMA journal_mode=WAL") log.debug("check data-db schema") reset_blocks = False for table_name, table in data_base.metadata.tables.items(): log.debug("check {}-db schema".format(table.name)) if not check_table_ddl_against_model(data_db, table): log.debug("{}-db schema outdated, resetting".format(table.name)) reset_blocks = True if engine.dialect.has_table(engine, table_name): table.drop(engine) else: log.debug("{}-db schema up to date".format(table.name)) data_base.metadata.create_all(engine) if reset_blocks: data_db().query(Block).delete() return data_db
def get_active_rpc_client(override=None): from app.models import Profile from app.models.db import profile_session_scope with profile_session_scope() as session: profile = override or Profile.get_active(session) assert isinstance(profile, Profile) return RpcClient(profile.rpc_host, profile.rpc_port, profile.rpc_user, profile.rpc_password, profile.rpc_use_ssl)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.setupUi(self) from app.models.db import profile_session_scope with profile_session_scope() as session: self.profile = Profile.get_active(session) self.on_profile_changed(self.profile) signals.profile_changed.connect(self.on_profile_changed)
def getruntimeparams(): """Update wallet main address on current profile""" client = get_active_rpc_client() with profile_session_scope() as session: profile = Profile.get_active(session) params = client.getruntimeparams() if params.handshakelocal != profile.address: profile.address = params.handshakelocal
def init_profile_db(): fp = app.PROFILE_DB_FILEPATH log.debug('init profile db at {}'.format(fp)) engine = sqlalchemy.create_engine('sqlite:///{}'.format(fp)) profile_db.configure(bind=engine) engine.execute("PRAGMA journal_mode=WAL") log.debug("check {}-db schema".format(Profile.__table__.name)) backup_profiles = [] if not check_table_ddl_against_model(profile_db, Profile.__table__): log.debug("{}-db schema outdated, resetting".format( Profile.__table__.name)) if engine.dialect.has_table(engine, "profiles"): for profile in profile_db().execute( 'SELECT * FROM profiles').fetchall(): backup_profiles.append(profile) Profile.__table__.drop(engine) elif engine.dialect.has_table(engine, "profile"): for profile in profile_db().execute( 'SELECT * FROM profile').fetchall(): backup_profiles.append(profile) else: log.debug("{}-db schema up to date".format(Profile.__table__.name)) # create the database Profile_Base.metadata.create_all(engine) with profile_session_scope() as session: for profile in backup_profiles: session.add( Profile( name=profile.name if 'name' in profile else '', rpc_host=profile.rpc_host if 'rpc_host' in profile else '127.0.0.1', rpc_port=profile.rpc_port if 'rpc_port' in profile else '9719', rpc_user=profile.rpc_user if 'rpc_user' in profile else 'multichainrpc', rpc_password=profile.rpc_password if 'rpc_password' in profile else '', rpc_use_ssl=profile.rpc_use_ssl if 'rpc_use_ssl' in profile else 0, manage_node=profile.manage_node if 'manage_node' in profile else 1, exit_on_close=profile.exit_on_close if 'exit_on_close' in profile else 1, active=profile.active if 'active' in profile else 0, alias=profile.alias if 'alias' in profile else '', address=profile.address if 'address' in profile else '', balance=profile.balance if 'balance' in profile else 0, is_admin=profile.is_admin if 'is_admin' in profile else 0, is_miner=profile.is_miner if 'is_miner' in profile else 0, )) return profile_db
def already_revoked(data_db, perm_type): from app.models import Profile from app.models.db import profile_session_scope with profile_session_scope() as session: profile = Profile.get_active(session) return data_db.query( PendingVote.address_to, PendingVote.perm_type).filter( (PendingVote.address_from == profile.address) & (PendingVote.start_block == 0) & (PendingVote.end_block == 0) & (PendingVote.perm_type == perm_type)).all()
def already_granted(data_db): from app.models import Permission, Profile from app.models.db import profile_session_scope with profile_session_scope() as session: profile = Profile.get_active(session) return data_db.query( PendingVote.address_to, PendingVote.perm_type).filter( (PendingVote.address_from == profile.address) & (PendingVote.start_block == 0) & (PendingVote.end_block == Permission.MAX_END_BLOCK)).all()
def init_node_data_dir(): from app.models import Profile from app.models.db import profile_session_scope with profile_session_scope() as session: profile = Profile.get_active(session) ndd = os.path.join(app.DATA_DIR, 'node_' + profile.name) if profile.manage_node: if not os.path.exists(ndd): log.debug('create node data dir {}'.format(ndd)) os.makedirs(ndd, exist_ok=True) return ndd
def __init__(self, *args, **kwargs): self.perm_type = kwargs.pop('perm_type') QTableView.__init__(self, *args, **kwargs) self.setMinimumWidth(400) try: self.profile = self.parent().profile except AttributeError: # In case of standalone usage with profile_session_scope() as session: self.profile = Profile.get_active(session) signals.is_admin_changed.connect(self.is_admin_changed) # self.pressed.connect(self.on_cell_clicked) self.table_model = PermissionModel(self, perm_type=self.perm_type) self.setModel(self.table_model) font = QFont() font.setFamily("Roboto Light") font.setPointSize(10) self.setColumnHidden(5, not self.profile.is_admin) header = self.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.Interactive) header.setSectionResizeMode(1, QHeaderView.Stretch) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(3, QHeaderView.ResizeToContents) header.setSectionResizeMode(4, QHeaderView.ResizeToContents) header.setSectionResizeMode(5, QHeaderView.ResizeToContents) header.setFont(font) # Row height self.verticalHeader().setVisible(False) self.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) self.verticalHeader().setDefaultSectionSize(40) self.setFont(font) self.setAlternatingRowColors(True) self.setSelectionMode(QAbstractItemView.SingleSelection) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setShowGrid(False) # TODO implement comminity tables sorting self.setSortingEnabled(False) self.setCornerButtonEnabled(True) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.openCustomMenu) self.balance_is_zero = True self.create_table_buttons(self.balance_is_zero) signals.on_balance_status_changed.connect( self.on_balance_status_changed)
def start(self, *args, **kwargs): """Start node with active profile settings. :param str initprivkey: Optional WIF encoded private key for first time init. """ initprivkey = kwargs.pop('initprivkey', None) try: self.profile = self.parent().profile except AttributeError: # In case of standalone usage from app.models.db import profile_session_scope with profile_session_scope() as session: self.profile = Profile.get_active(session) assert isinstance(self.profile, Profile) assert self.profile.manage_node, "active profile does not want to manage node" if self.state() == self.NotRunning: node_path = os.path.join(app.APP_DIR, 'app/bin/multichaind') if self.reindex_required: log.debug('starting node at: {} with -reindex=1'.format(node_path)) else: log.debug('starting node at: {}'.format(node_path)) # TODO only launch full bootstrap ip in first launch launch_args = [ app.NODE_BOOTSTRAP, '-server=1', # '-daemon', '-autosubscribe=assets,streams', '-autocombineminconf=4294967294', # '-maxshowndata=32', # '-printtoconsole', '-reindex=' + ("1" if self.reindex_required else "0"), # '-shortoutput', '-rpcuser={}'.format(self.profile.rpc_user), '-rpcpassword={}'.format(self.profile.rpc_password), '-rpcbind={}'.format(self.profile.rpc_host), '-rpcallowip={}'.format(self.profile.rpc_host), '-rpcport={}'.format(self.profile.rpc_port), '-datadir={}'.format(init_node_data_dir()), ] if initprivkey is not None: launch_args.append('-initprivkey={}'.format(initprivkey)) super().start(node_path, launch_args, QIODevice.ReadOnly) self.reindex_required = False else: log.debug('node already started - state: {}'.format(self.state()))
def getinfo(): """Update latest wallet balance on current profile""" client = get_active_rpc_client() with profile_session_scope() as session: profile = Profile.get_active(session) try: info = client.getinfo() signals.getinfo.emit(info) new_balance = Decimal(str(info.balance)) if new_balance != profile.balance: profile.balance = Decimal(info.balance) except Exception as e: log.debug(e)
def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) from app.models.db import profile_session_scope with profile_session_scope() as session: self.profile = Profile.get_active(session) self.on_profile_changed(self.profile) self.edit_alias.setText(self.profile.alias) self.edit_alias.textChanged.connect(self.on_alias_changed) signals.profile_changed.connect(self.on_profile_changed) self.adjustSize() self.buttonBox.button(QDialogButtonBox.Save).clicked.connect(self.save) self.buttonBox.button(QDialogButtonBox.Save).setDisabled(True)
def on_application_start(self): init_profile_db() self.updater = Updater(self) self.node = Node(self) self.aboutToQuit.connect(self.cleanup) from app.models.db import profile_session_scope with profile_session_scope() as session: is_first_start = app.is_first_start(session) if is_first_start: wizard = SetupWizard() if wizard.exec() == SetupWizard.Rejected: QtWidgets.qApp.quit() return else: init_data_db() # Initialize main window self.ui = self.main_widget() # Init TrayIcon self.tray_icon = QtWidgets.QSystemTrayIcon(self) self.tray_icon.setIcon(QIcon(':images/resources/app_icon.png')) self.tray_icon.activated.connect(self.on_tray_activated) show_action = QtWidgets.QAction("Show", self) quit_action = QtWidgets.QAction("Exit", self) hide_action = QtWidgets.QAction("Hide", self) show_action.triggered.connect(self.ui.show) hide_action.triggered.connect(self.ui.hide) quit_action.triggered.connect(QtWidgets.qApp.quit) tray_menu = QtWidgets.QMenu() tray_menu.addAction(show_action) tray_menu.addAction(hide_action) tray_menu.addAction(quit_action) self.tray_icon.setContextMenu(tray_menu) self.tray_icon.show() # Shortcuts if hasattr(self.ui, 'node'): self.ui.debug_shortcut = QtWidgets.QShortcut( 'Ctrl+K', self.ui, self.node.kill) self.ui.debug_shortcut = QtWidgets.QShortcut( 'Ctrl+S', self.ui, self.node.stop) self.ui.debug_shortcut = QtWidgets.QShortcut( 'Ctrl+R', self.ui, self.node.start)
def page7_sync_initialize_page(self): if self._mnemonic and not self._address: self._address = main_address_from_mnemonic(self._mnemonic) self.label_address.setText(self._address) img = ImageQt(qrcode.make(self._address, box_size=3)) self.label_qr_code.setPixmap(QPixmap.fromImage(img)) if not exists(app.DATA_DIR): self.log('Creating data dir at: %s' % app.DATA_DIR) init_data_dir() self.log('Initialize profile database at: %s' % app.PROFILE_DB_FILEPATH) with profile_session_scope() as session: if self._manage_node: Profile.create_default_profile(session) elif self._connection_tested: session.merge( Profile( name=self.edit_rpc_host.text(), rpc_host=self.edit_rpc_host.text(), rpc_port=self.edit_rpc_port.text(), rpc_user=self.edit_rpc_user.text(), rpc_password=self.edit_rpc_password.text(), rpc_use_ssl=self.cbox_use_ssl.isChecked(), manage_node=False, exit_on_close=True, active=True, )) self.log('Initialize node-sync database') init_data_db() # This fixes our problem with the locked database # We have no idea why, but we shouldn't delete this code until we have a better solution with data_session_scope() as session: session.query('DELETE FROM mining_reward') if self._manage_node: self.node.start(initprivkey=main_wif_from_mnemonic(self._mnemonic)) else: self._database_sync = True if not self.updater.isRunning(): self.updater.start()
def run(self): synced_blockhash = '' with profile_session_scope() as profile_session: profile = Profile.get_active(profile_session) with data_session_scope() as data_session: profile.alias = Alias.get_alias_by_address(data_session, profile.address) while True: log.debug('check for new blocks') try: # This triggers Network Info widget update that we always want blockchain_info = sync.getblockchaininfo() # The node is downloading blocks if it has more headers than blocks if blockchain_info.blocks != blockchain_info.headers or blockchain_info.reindex: log.debug('blockchain syncing - skip expensive rpc calls') self.sleep(self.UPDATE_INTERVALL) continue node_block_hash = blockchain_info.bestblockhash except Exception as e: log.exception('cannot get bestblock via rpc: %s' % e) self.sleep(self.UPDATE_INTERVALL) continue sync.getinfo() if node_block_hash != synced_blockhash: log.debug('starting full sync round') for sync_func in self.sync_funcs: try: log.debug('updating %s' % sync_func.__name__) sync_func() except Exception as e: log.exception(e) synced_blockhash = node_block_hash signals.sync_cycle_finished.emit() self.sleep(self.UPDATE_INTERVALL)
def __init__(self, parent=None): super().__init__(parent) self.table_model = CandidateModel(self) self.setModel(self.table_model) self.setMinimumWidth(400) font = QFont() font.setFamily("Roboto Light") font.setPointSize(10) header = self.horizontalHeader() header.setSectionResizeMode(0, QHeaderView.ResizeToContents) header.setSectionResizeMode(1, QHeaderView.Stretch) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(3, QHeaderView.ResizeToContents) header.setSectionResizeMode(4, QHeaderView.ResizeToContents) header.setFont(font) # Row height self.verticalHeader().setVisible(False) self.verticalHeader().setSectionResizeMode(QHeaderView.Fixed) self.verticalHeader().setDefaultSectionSize(40) with profile_session_scope() as session: self.setColumnHidden(4, not Profile.get_active(session).is_admin) self.setFont(font) self.setAlternatingRowColors(True) self.setSelectionMode(QAbstractItemView.SingleSelection) self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setShowGrid(False) # TODO implement candidates table sorting self.setSortingEnabled(False) self.setCornerButtonEnabled(True) self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.openCustomMenu) self.create_table_buttons() signals.is_admin_changed.connect(self.is_admin_changed)
def setting_changed_exit_on_close(self, state): self.profile.exit_on_close = state == 2 with profile_session_scope() as session: session.add(self.profile)
def process_permissions(): # todo: check if we have new perms / votes client = get_active_rpc_client() try: perms = client.listpermissions("*", "*", True) except Exception as e: log.debug(e) return with data_session_scope() as session: session.query(Permission).delete() session.query(PendingVote).delete() with data_session_scope() as session: for perm in perms: perm_type = perm['type'] perm_start = perm['startblock'] perm_end = perm['endblock'] address = perm['address'] Address.create_if_not_exists(session, address) if perm_type not in [ enums.ISSUE, enums.CREATE, enums.MINE, enums.ADMIN ]: continue perm_obj = Permission(address=address, perm_type=perm_type, start_block=perm_start, end_block=perm_end) session.add(perm_obj) for vote in perm['pending']: start_block = vote['startblock'] end_block = vote['endblock'] # If candidate has already the permission continue. if start_block == perm['startblock'] and end_block == perm[ 'endblock']: continue for admin in vote['admins']: Address.create_if_not_exists(session, admin) vote_obj = PendingVote(address_from=admin, address_to=address, perm_type=perm_type, start_block=start_block, end_block=end_block) session.add(vote_obj) signals.votes_changed.emit() with profile_session_scope() as profile_db: profile = Profile.get_active(profile_db) with data_session_scope() as data_db: is_admin, is_miner = Permission.get_permissions_for_address( data_db, profile.address) if is_admin != profile.is_admin: profile.is_admin = is_admin signals.is_admin_changed.emit(is_admin) if is_miner != profile.is_miner: profile.is_miner = is_miner signals.is_miner_changed.emit(is_miner) signals.permissions_changed.emit()
def __init__(self, **kwargs): super().__init__(**kwargs) # Instantiate workers self.updater = QApplication.instance().updater self.node = QApplication.instance().node self.data_dir = helpers.init_data_dir() self.node_data_dir = helpers.init_node_data_dir() with profile_session_scope() as session: self.profile = Profile.get_active(session) # Setup Widgets self.setupUi(self) # Hide information widget font = QFont('Roboto Light', 10) self.label_info_text.setFont(font) self.btn_close_info.setFont(font) font.setUnderline(True) self.btn_info_action.setFont(font) self.widget_information.setHidden(True) self.btn_close_info.clicked.connect(self.hide_information) signals.new_unconfirmed.connect(self.show_transaction_info) self.information_type = None self.on_profile_changed(self.profile) signals.profile_changed.connect(self.on_profile_changed) self.permissions_changed() signals.permissions_changed.connect(self.permissions_changed) # Init Navigation self.btn_grp_nav.setId(self.btn_nav_wallet, 0) self.btn_grp_nav.setId(self.btn_nav_iscc, 1) self.btn_grp_nav.setId(self.btn_nav_timestamp, 2) self.btn_grp_nav.setId(self.btn_nav_token, 3) self.btn_grp_nav.setId(self.btn_nav_community, 4) self.btn_grp_nav.setId(self.btn_nav_settings, 5) self.btn_nav_wallet.setChecked(True) self.wgt_content.setCurrentIndex(0) # Patch custom widgets self.tab_widget_cummunity.setStyleSheet( 'QPushButton {padding: 5 12 5 12; font: 10pt "Roboto Light"}') self.gbox_wallet_transactions.setParent(None) self.gbox_wallet_send.setParent(None) wallet_send = WalletSend(self) self.lout_page_wallet_v.addWidget(wallet_send) wallet_history = WalletHistory(self) self.lout_page_wallet_v.addWidget(wallet_history) widget_iscc = WidgetISCC(self) self.lout_page_iscc_v.addWidget(widget_iscc) widget_timestamp = WidgetTimestamping(self) self.lout_page_timestamp_v.addWidget(widget_timestamp) widget_token = WidgetToken(self) self.lout_page_token_v.addWidget(widget_token) self.table_validators.setParent(None) table_validators = CommunityTableView(self, perm_type=enums.MINE) self.tab_validators.layout().insertWidget(0, table_validators) self.table_guardians.setParent(None) table_guardians = CommunityTableView(self, perm_type=enums.ADMIN) self.tab_guardians.layout().insertWidget(0, table_guardians) self.table_candidates.setParent(None) table_candidates = CandidateTableView(self) self.tab_candidates.layout().insertWidget(0, table_candidates) # Statusbar self.label_statusbar = QtWidgets.QLabel('') self.statusbar.addPermanentWidget(self.label_statusbar) # Dialog Button hookups invite_dialog = InviteDialog(self) self.button_invite_canditate.clicked.connect(invite_dialog.exec) apply_dialog = ApplyDialog(self) self.button_apply_guardian.clicked.connect(apply_dialog.exec) self.button_apply_validator.clicked.connect(apply_dialog.exec) # Settings self.check_box_exit_on_close.setChecked(self.profile.exit_on_close) self.check_box_exit_on_close.stateChanged['int'].connect( self.setting_changed_exit_on_close) self.check_manage_node.setChecked(self.profile.manage_node) self.check_manage_node.stateChanged['int'].connect( self.setting_changed_manage_node) self.btn_alias_change.clicked.connect(self.on_change_alias) # Connections signals.getinfo.connect(self.getinfo) signals.getblockchaininfo.connect(self.getblockchaininfo) signals.node_started.connect(self.node_started) signals.rpc_error.connect(self.rpc_error) signals.blockschanged.connect(self.getdatabaseinfo) signals.on_balance_status_changed.connect( self.on_balance_status_changed) with data_session_scope() as session: from app.models import Block self.progress_bar_database_info.setValue( session.query(Block).count()) if self.profile.manage_node: # Todo check for existing node process self.node.start() else: # No managed node to wait for... start updater self.updater.start() self.show()
from app.models import Profile from app.models.db import profile_session_scope with profile_session_scope() as session: profile = override or Profile.get_active(session) assert isinstance(profile, Profile) return RpcClient(profile.rpc_host, profile.rpc_port, profile.rpc_user, profile.rpc_password, profile.rpc_use_ssl) class DecimalEncoder(json.JSONEncoder): """Custom json encoder that supports Decimal""" def default(self, o): if isinstance(o, decimal.Decimal): return float(o) return super(DecimalEncoder, self).default(o) if __name__ == '__main__': from pprint import pprint import app from app.models import Profile from app.models.db import profile_session_scope app.init() with profile_session_scope() as session: print(Profile.get_active(session)) client = get_active_rpc_client() # pprint(client.getmultibalances('*', '*', 1, False, False)) # pprint(client.getmultibalances('*', '*', 0, False, True)) print(client.getbestblockhash()) pprint(client.listwallettransactions(1))