示例#1
0
                    timestamp = op["timestamp"]                
                if share_type.lower() in ["sharetransfer"]:
                    if op["shares"] > 0 and op["sponsor"] in member_data and op["account"] in member_data:
                        if op["shares"] > member_data[op["account"]]["shares"]:
                            continue
                        member_data[op["account"]]["shares"] -= op["shares"]
                        member_data[op["sponsor"]]["shares"] += op["shares"]

                        member_data[op["sponsor"]]["latest_enrollment"] = timestamp
                        member_data[op["sponsor"]].append_share_age(timestamp, op["shares"])
                elif share_type.lower() in ["delegation"]:
                    if op["shares"] > 0 and op["sponsor"] in member_data:
                        # print("del. bonus_shares: %s - %d" % (op["sponsor"], op["shares"]))
                        delegation[op["sponsor"]] = op["shares"]
                    elif op["vests"] > 0 and op["sponsor"] in member_data:
                        sp = stm.vests_to_sp(float(op["vests"]))
                        delegation[op["sponsor"]] = int(sp / sp_share_ratio)
                    # memo_sp_delegation(transferMemos, memo_transfer_acc, op["sponsor"], delegation[op["sponsor"]], sp_share_ratio)
                    delegation_timestamp[op["sponsor"]] = timestamp
                elif share_type.lower() in ["removeddelegation"]:
                    delegation[op["sponsor"]] = 0
                    delegation_timestamp[op["sponsor"]] = None
                    
                elif share_type.lower() in ["mgmttransfer"]:
                    if op["shares"] > 0 and op["sponsor"] in member_data and op["account"] in member_data:
                        if op["shares"] > member_data[op["account"]]["bonus_shares"]:
                            continue
                        member_data[op["account"]]["bonus_shares"] -= op["shares"]
                        member_data[op["sponsor"]]["bonus_shares"] += op["shares"]

                        member_data[op["sponsor"]]["latest_enrollment"] = timestamp
    stm = Steem()
    price = Amount(stm.get_current_median_history()["base"])
    reps = [0]
    for i in range(26, 91):
        reps.append(int(10**((i - 25) / 9 + 9)))
    # reps = np.logspace(9, 16, 60)
    used_power = stm._calc_resulting_vote()
    last_sp = 0
    sp_list = []
    rep_score_list = []
    for goal_rep in reps:
        score = reputation_to_score(goal_rep)
        rep_score_list.append(score)
        needed_rshares = int(goal_rep) << 6
        needed_vests = needed_rshares / used_power / 100
        needed_sp = stm.vests_to_sp(needed_vests)
        sp_list.append(needed_sp / 1000)
        # print("| %.1f | %.2f | %.2f  | " % (score, needed_sp / 1000, needed_sp / 1000 - last_sp / 1000))
        last_sp = needed_sp

    plt.figure(figsize=(12, 6))
    opts = {'linestyle': '-', 'marker': '.'}
    plt.semilogx(sp_list, rep_score_list, label="Reputation", **opts)
    plt.grid()
    plt.legend()
    plt.title("Required number of 1k SP upvotes to reach certain reputation")
    plt.xlabel("1k SP votes")
    plt.ylabel("Reputation")
    plt.show()
    # plt.savefig("rep_based_on_votes.png")
示例#3
0
                delegation_list.append(d)
        for d in trxStorage.get_share_type(share_type="DelegationLeased"):
            if d["share_type"] == "DelegationLeased":
                delegation_list.append(d)
        for d in trxStorage.get_share_type(share_type="RemovedDelegation"):
            if d["share_type"] == "RemovedDelegation":
                delegation_list.append(d)

        sorted_delegation_list = sorted(
            delegation_list,
            key=lambda x: (datetime.utcnow() - x["timestamp"]).total_seconds(),
            reverse=True)

        for d in sorted_delegation_list:
            if d["share_type"] == "Delegation":
                delegation[d["account"]] = stm.vests_to_sp(float(d["vests"]))
                delegation_timestamp[d["account"]] = d["timestamp"]
                delegation_shares[d["account"]] = d["shares"]
            elif d["share_type"] == "DelegationLeased":
                delegation[d["account"]] = 0
                delegation_timestamp[d["account"]] = d["timestamp"]
                delegation_shares[d["account"]] = d["shares"]
            elif d["share_type"] == "RemovedDelegation":
                delegation[d["account"]] = 0
                delegation_timestamp[d["account"]] = d["timestamp"]
                delegation_shares[d["account"]] = 0

        delegation_leased = {}
        delegation_shares = {}
        print("update delegation")
        delegation_account = delegation
示例#4
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(QMainWindow, self).__init__()
        # Set up the user interface from Designer.
        self.setupUi(self)

        self.setAccessibleName("Hive Desktop")
        self.redrawLock = Lock()
        self.updateLock = Lock()

        self.optionsDialog = dialogs.Options(self)
        self.aboutDialog = dialogs.About(
            self,
            copyright='holger80',
            programName='Hive Desktop',
            version=VERSION,
            website='https://github.com/holgern/hivedesktop',
            websiteLabel='Github',
            comments=
            '"Welcome to Hive desktop!\n This is the first release for testing qt5.\n Please vote for holger80 as witness, if you like this :).',
            licenseName='GPL-3.0',
            # licenseUrl=helpers.joinpath_to_cwd('LICENSE').as_uri(),
            authors=('holger80', ),
            # dependencies=[l.strip() for l in requirements.readlines()],
        )
        self.mdrenderer = MDRenderer(str(helpers.joinpath_to_cwd('themes')))

        # tmpfile = helpers.mktemp(prefix='hivedesktop', suffix='.html')

        self.post = {"body": "##test", "authorperm": "@test/test"}
        self.thread = threads.MDThread(self)

        # self.webview.url = tmpfile.as_uri()

        self.feedListWidget.currentRowChanged.connect(
            self.change_displayed_post, Qt.QueuedConnection)

        self.timer = QTimer()
        self.timer.timeout.connect(self.refresh_account_thread)

        self.timer2 = QTimer()
        self.timer2.timeout.connect(self.update_account_hist_thread)

        self.timer3 = QTimer()
        self.timer3.timeout.connect(self.update_account_feed_thread)

        self.cache_path = QStandardPaths.writableLocation(
            QStandardPaths.CacheLocation)
        self.db_type = "shelve"
        self.feed = []
        self.post = None
        # Get settings
        settings = QSettings()
        # Get checkbox state with speciying type of checkbox:
        # type=bool is a replacement of toBool() in PyQt5
        check_state = settings.value(SETTINGS_TRAY, True, type=bool)
        hist_info_check_state = settings.value(SETTINGS_HIST_INFO,
                                               True,
                                               type=bool)
        account_state = settings.value(SETTINGS_ACCOUNT, "", type=str)
        # Set state
        self.accountHistNotificationCheckBox.setChecked(hist_info_check_state)
        self.autoRefreshCheckBox.setChecked(check_state)
        if check_state:
            self.timer.start(5000)
            self.timer2.start(15000)
            self.timer3.start(60000)
        self.accountLineEdit.setText(account_state)
        # connect the slot to the signal by clicking the checkbox to save the state settings
        self.autoRefreshCheckBox.clicked.connect(self.save_check_box_settings)
        self.accountHistNotificationCheckBox.clicked.connect(
            self.save_check_box_settings)
        self.accountLineEdit.editingFinished.connect(
            self.save_account_settings)
        self.actionAbout.triggered.connect(self.about)
        self.actionOptions.triggered.connect(self.options)
        self.threadpool = QThreadPool()

        self.minimizeAction = QAction("Mi&nimize", self, triggered=self.hide)
        self.maximizeAction = QAction("Ma&ximize",
                                      self,
                                      triggered=self.showMaximized)
        self.restoreAction = QAction("&Restore",
                                     self,
                                     triggered=self.showNormal)

        menu = QMenu()
        menu.addAction(self.minimizeAction)
        menu.addAction(self.maximizeAction)
        menu.addAction(self.restoreAction)
        menu.addSeparator()
        # aboutAction = menu.addAction("about")
        # aboutAction.triggered.connect(self.about)
        exitAction = menu.addAction("Exit")
        exitAction.triggered.connect(self.closeApp)

        self.tray = QSystemTrayIcon(QIcon(':/icons/icon.ico'))

        self.tray.setContextMenu(menu)

        self.tray.setToolTip("Hive Desktop!")
        self.tray.setObjectName("Hive Desktop")
        self.setWindowTitle("Hive Desktop")
        self.tray.show()

        splash_pix = QPixmap(':/icons/splash.png')
        splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
        splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        splash.setEnabled(False)

        splash.show()
        splash.showMessage("<h1><font color='green'>starting...</font></h1>",
                           Qt.AlignTop | Qt.AlignCenter, Qt.black)

        account = account_state
        nodelist = NodeList()
        nodelist.update_nodes()
        self.stm = Steem(node=nodelist.get_nodes(hive=True))
        if account != "":
            try:
                self.hist_account = Account(account, steem_instance=self.stm)
            except:
                self.hist_account = None
        else:
            self.hist_account = None
        if self.hasFocus is not None:
            self.init_new_account()
        # self.button.clicked.connect(lambda: self.text.setText(_get_quote(self.hist_account, self.stm)))
        self.refreshPushButton.clicked.connect(self.refresh_account_thread)
        self.refreshPushButton.clicked.connect(self.update_account_hist_thread)
        self.accountLineEdit.editingFinished.connect(self.update_account_info)
        splash.deleteLater()
        self.tray.showMessage("Ready", "Account history loaded!")

    def triggeredPreview(self):
        self.authorLabel.setText(self.post["author"])
        self.titleLabel.setText(self.post["title"])
        self.thread.start()

    @pyqtSlot(str)
    def cbMDThread(self, html):
        self.webview.setHtml(html)

    def closeEvent(self, event):
        if self.tray.isVisible():
            QMessageBox.information(
                self, "Hive Desktop",
                "The program will keep running in the system tray. To "
                "terminate the program, choose <b>Quit</b> in the "
                "context menu of the system tray entry.")
            self.hide()
            event.ignore()

    def closeApp(self):
        self.store_account_hist()
        sys.exit()

    def about(self):
        self.aboutDialog.exec_()

    def options(self):
        self.optionsDialog.exec_()

    # Slot checkbox to save the settings
    def save_check_box_settings(self):
        settings = QSettings()
        settings.setValue(SETTINGS_HIST_INFO,
                          self.accountHistNotificationCheckBox.isChecked())
        settings.setValue(SETTINGS_TRAY, self.autoRefreshCheckBox.isChecked())
        if self.autoRefreshCheckBox.isChecked():
            self.timer.start(5000)
            self.timer2.start(15000)
            self.timer3.start(60000)
        else:
            self.timer.stop()
            self.timer2.stop()
            self.timer3.stop()
        settings.sync()

    # Slot checkbox to save the settings
    def save_account_settings(self):
        settings = QSettings()
        settings.setValue(SETTINGS_ACCOUNT, self.accountLineEdit.text())
        settings.sync()

    def update_account_info(self):
        if self.hist_account is None or self.hist_account[
                "name"] != self.accountLineEdit.text():
            self.store_account_hist()
            try:
                self.hist_account = Account(self.accountLineEdit.text(),
                                            steem_instance=self.stm)
            except:
                self.hist_account = None
            self.init_new_account()

    def init_new_account(self):
        if self.hist_account is not None:
            self.db = database.Database(self.db_type, self.cache_path,
                                        self.hist_account["name"])
        self.refresh_account()
        self.init_account_hist()
        self.update_account_hist()
        self.update_account_feed()
        self.store_account_hist()

    def refresh_account_thread(self):
        worker = Worker(self.refresh_account)
        self.threadpool.start(worker)

    def refresh_account(self):
        if self.hist_account is None:
            return
        self.hist_account.refresh()
        self.accountInfoGroupBox.setTitle(
            "%s (%.3f)" % (self.hist_account["name"], self.hist_account.rep))
        with self.redrawLock:
            self.votePowerProgressBar.setValue(int(self.hist_account.vp))
            if self.hist_account.vp == 100:
                self.votePowerProgressBar.setFormat("%.2f %%" %
                                                    (self.hist_account.vp))
            else:
                self.votePowerProgressBar.setFormat(
                    "%.2f %%, full in %s" %
                    (self.hist_account.vp,
                     self.hist_account.get_recharge_time_str()))
        down_vp = self.hist_account.get_downvoting_power()
        with self.redrawLock:
            self.downvotePowerProgressBar.setValue(int(down_vp))
            if down_vp == 100:
                self.downvotePowerProgressBar.setFormat("%.2f %%" % (down_vp))
            else:
                self.downvotePowerProgressBar.setFormat(
                    "%.2f %%, full in %s" %
                    (down_vp,
                     self.hist_account.get_recharge_time(
                         starting_voting_power=down_vp)))

        self.votePowerLabel.setText("Vote Power, a 100%% vote is %.3f $" %
                                    (self.hist_account.get_voting_value_SBD()))
        self.downvotePowerLabel.setText("DownVote Power")
        self.STEEMLabel.setText(str(self.hist_account["balance"]))
        self.SBDLabel.setText(str(self.hist_account["sbd_balance"]))
        self.SPLabel.setText(
            "%.3f HP" %
            self.stm.vests_to_sp(self.hist_account["vesting_shares"]))
        try:
            rc_manabar = self.hist_account.get_rc_manabar()
            with self.redrawLock:
                self.RCProgressBar.setValue(int(rc_manabar["current_pct"]))
                self.RCProgressBar.setFormat(
                    "%.2f %%, full in %s" %
                    (rc_manabar["current_pct"],
                     self.hist_account.get_manabar_recharge_time_str(
                         rc_manabar)))

            rc = self.hist_account.get_rc()
            estimated_rc = int(rc["max_rc"]) * rc_manabar["current_pct"] / 100
            rc_calc = RC(steem_instance=self.stm)
            self.RCLabel.setText(
                "RC (%.0f G RC of %.0f G RC)" %
                (estimated_rc / 10**9, int(rc["max_rc"]) / 10**9))
            ret = "--- Approx Costs ---\n"
            ret += "comment - %.2f G RC - enough RC for %d comments\n" % (
                rc_calc.comment() / 10**9, int(
                    estimated_rc / rc_calc.comment()))
            ret += "vote - %.2f G RC - enough RC for %d votes\n" % (
                rc_calc.vote() / 10**9, int(estimated_rc / rc_calc.vote()))
            ret += "transfer - %.2f G RC - enough RC for %d transfers\n" % (
                rc_calc.transfer() / 10**9,
                int(estimated_rc / rc_calc.transfer()))
            ret += "custom_json - %.2f G RC - enough RC for %d custom_json\n" % (
                rc_calc.custom_json() / 10**9,
                int(estimated_rc / rc_calc.custom_json()))
            self.text.setText(ret)
        except:
            rc_manabar = None

    def store_account_hist(self):
        if self.hist_account is None:
            return
        self.db.store_account_hist(self.account_history,
                                   self.append_hist_info["trx_ids"])

    def init_account_hist(self):
        if self.hist_account is None:
            return
        b = Blockchain(steem_instance=self.stm)
        latest_block_num = b.get_current_block_num()
        start_block_num = latest_block_num - (20 * 60 * 24)
        self.account_history = []
        self.account_hist_info = {"start_block": 0, "trx_ids": []}
        self.append_hist_info = {"start_block": 0, "trx_ids": []}

        if self.db.has_account_hist():
            self.account_history, trx_ids = self.db.load_account_hist()
            if self.account_history[0]["block"] <= start_block_num:
                self.append_hist_info["start_block"] = self.account_history[
                    -1]["block"]
                self.append_hist_info["trx_ids"] = trx_ids
                return

        self.lastUpvotesListWidget.clear()
        self.lastCurationListWidget.clear()
        self.lastAuthorListWidget.clear()
        self.accountHistListWidget.clear()
        start_block = 0
        trx_ids = []
        for op in self.hist_account.history(start=start_block_num):
            if op["block"] < start_block:
                continue
            elif op["block"] == start_block:
                if op["trx_id"] in trx_ids:
                    continue
                else:
                    trx_ids.append(op["trx_id"])
            else:
                trx_ids = [op["trx_id"]]
            start_block = op["block"]
            self.account_history.append(op)
        self.append_hist_info["start_block"] = start_block
        self.append_hist_info["trx_ids"] = trx_ids

    def append_account_hist(self):
        if self.hist_account is None:
            return
        start_block = self.append_hist_info["start_block"]
        trx_ids = self.append_hist_info["trx_ids"]
        for op in self.hist_account.history(start=start_block - 20,
                                            use_block_num=True):
            if op["block"] < start_block:
                continue
            elif op["block"] == start_block:
                if op["trx_id"] in trx_ids:
                    continue
                else:
                    trx_ids.append(op["trx_id"])
            else:
                trx_ids = [op["trx_id"]]

            start_block = op["block"]
            # print("Write %d" % op["index"])
            self.account_history.append(op)
        self.append_hist_info["start_block"] = start_block
        self.append_hist_info["trx_ids"] = trx_ids

    def update_account_hist_thread(self):
        worker = Worker(self.update_account_hist)
        self.threadpool.start(worker)

    def update_account_feed_thread(self):
        worker = Worker(self.update_account_feed)
        self.threadpool.start(worker)

    @pyqtSlot(int)
    def change_displayed_post(self, row):
        if row < 0:
            return
        if len(self.feed) == 0:
            return
        if len(self.feed) <= row:
            return
        #index = self.feedListWidget.currentIndex()
        #row = index.row()
        self.post = self.feed[row]
        with self.updateLock:
            self.triggeredPreview()

    def update_account_feed(self):
        if self.hist_account is None:
            return
        updated_feed = self.hist_account.get_account_posts()
        if len(self.feed) == 0:
            self.feed = updated_feed
        else:
            for post in updated_feed[::-1]:
                found = False
                for p in self.feed:
                    if post["authorperm"] == p["authorperm"]:
                        found = True
                if not found:
                    self.feed.insert(0, post)
                    self.tray.showMessage(post["author"], post["title"])
        with self.updateLock:
            if self.post is None:
                self.post = self.feed[0]
                self.triggeredPreview()

            self.feedListWidget.currentRowChanged.disconnect(
                self.change_displayed_post)
            self.feedListWidget.clear()
            for post in self.feed[::-1]:
                post_text = "%s - %s" % (post["author"], post["title"])
                post_item = QListWidgetItem()
                post_item.setText(post_text)
                post_item.setToolTip(post["author"])
                self.feedListWidget.insertItem(0, post_item)
            self.feedListWidget.currentRowChanged.connect(
                self.change_displayed_post, Qt.QueuedConnection)

    def update_account_hist(self):
        if self.hist_account is None:
            return
        votes = []
        daily_curation = 0
        daily_author_SP = 0
        daily_author_SBD = 0
        daily_author_STEEM = 0
        self.append_account_hist()

        new_op_found = False

        start_block = self.account_hist_info["start_block"]
        if start_block == 0:
            first_call = True
        else:
            first_call = False
        trx_ids = self.account_hist_info["trx_ids"]

        for op in self.account_history:
            if op["block"] < start_block:
                # last_block = op["block"]
                continue
            elif op["block"] == start_block:
                if op["trx_id"] in trx_ids:
                    continue
                else:
                    trx_ids.append(op["trx_id"])
            else:
                trx_ids = [op["trx_id"]]
            start_block = op["block"]
            new_op_found = True
            op_timedelta = formatTimedelta(
                addTzInfo(datetime.utcnow()) -
                formatTimeString(op["timestamp"]))
            op_local_time = formatTimeString(op["timestamp"]).astimezone(
                tz.tzlocal())
            # print("Read %d" % op["index"])
            if op["type"] == "vote":
                if op["voter"] == self.hist_account["name"]:
                    continue
                if op["weight"] >= 0:

                    self.lastUpvotesListWidget.insertItem(
                        0, "%s - %s (%.2f %%) upvote %s" %
                        (op_timedelta, op["voter"], op["weight"] / 100,
                         op["permlink"]))
                    hist_item = "%s - %s - %s (%.2f %%) upvote %s" % (
                        op_local_time, op["type"], op["voter"],
                        op["weight"] / 100, op["permlink"])
                    tray_item = "%s - %s (%.2f %%) upvote %s" % (
                        op["type"], op["voter"], op["weight"] / 100,
                        op["permlink"])
                else:
                    hist_item = "%s - %s - %s (%.2f %%) downvote %s" % (
                        op_local_time, op["type"], op["voter"],
                        op["weight"] / 100, op["permlink"])
                    tray_item = "%s - %s (%.2f %%) downvote %s" % (
                        op["type"], op["voter"], op["weight"] / 100,
                        op["permlink"])

                self.accountHistListWidget.insertItem(0, hist_item)
            elif op["type"] == "curation_reward":
                curation_reward = self.stm.vests_to_sp(
                    Amount(op["reward"], steem_instance=self.stm))
                self.lastCurationListWidget.insertItem(
                    0, "%s - %.3f HP for %s" %
                    (op_timedelta, curation_reward,
                     construct_authorperm(op["comment_author"],
                                          op["comment_permlink"])))
                hist_item = "%s - %s - %.3f HP for %s" % (
                    op_local_time, op["type"], curation_reward,
                    construct_authorperm(op["comment_author"],
                                         op["comment_permlink"]))
                tray_item = "%s - %.3f HP for %s" % (
                    op["type"], curation_reward,
                    construct_authorperm(op["comment_author"],
                                         op["comment_permlink"]))
                self.accountHistListWidget.insertItem(0, hist_item)
            elif op["type"] == "author_reward":
                sbd_payout = (Amount(op["sbd_payout"],
                                     steem_instance=self.stm))
                steem_payout = (Amount(op["steem_payout"],
                                       steem_instance=self.stm))
                sp_payout = self.stm.vests_to_sp(
                    Amount(op["vesting_payout"], steem_instance=self.stm))
                self.lastAuthorListWidget.insertItem(
                    0, "%s - %s %s %.3f HP for %s" %
                    (op_timedelta, str(sbd_payout), str(steem_payout),
                     sp_payout, op["permlink"]))
                hist_item = "%s - %s - %s %s %.3f SP for %s" % (
                    op_local_time, op["type"], str(sbd_payout),
                    str(steem_payout), sp_payout, op["permlink"])
                tray_item = "%s - %s %s %.3f SP for %s" % (
                    op["type"], str(sbd_payout), str(steem_payout), sp_payout,
                    op["permlink"])
                self.accountHistListWidget.insertItem(0, hist_item)
            elif op["type"] == "custom_json":
                hist_item = "%s - %s - %s" % (op_local_time, op["type"],
                                              op["id"])
                tray_item = "%s - %s" % (op["type"], op["id"])
                self.accountHistListWidget.insertItem(0, hist_item)
            elif op["type"] == "transfer":
                hist_item = "%s - %s - %s from %s" % (
                    op_local_time, op["type"],
                    str(Amount(op["amount"],
                               steem_instance=self.stm)), op["from"])
                tray_item = "%s - %s from %s" % (
                    op["type"],
                    str(Amount(op["amount"],
                               steem_instance=self.stm)), op["from"])
                self.accountHistListWidget.insertItem(0, hist_item)
            elif op["type"] == "comment":
                comment_type = "post"
                if op["parent_author"] != "":
                    hist_item = "%s - comment on %s - %s from %s" % (
                        op_local_time,
                        construct_authorperm(
                            op["parent_author"],
                            op["parent_permlink"]), op["title"], op["author"])
                    tray_item = "comment from %s: %s on %s" % (
                        op["author"], op["body"][:100], op["title"])
                else:
                    hist_item = "%s - post - %s from %s" % (
                        op_local_time, op["title"], op["author"])
                    tray_item = "post from %s: %s" % (op["author"],
                                                      op["title"])
                self.accountHistListWidget.insertItem(0, hist_item)
            else:
                hist_item = "%s - %s" % (op_local_time, op["type"])
                tray_item = "%s" % (op["type"])
                self.accountHistListWidget.insertItem(0, hist_item)

            if self.accountHistNotificationCheckBox.isChecked(
            ) and not first_call:
                self.tray.showMessage(self.hist_account["name"], tray_item)

        if new_op_found:
            self.account_hist_info["start_block"] = start_block
            self.account_hist_info["trx_ids"] = trx_ids

            for op in self.account_history:
                if op["type"] == "vote":
                    if op["voter"] == self.hist_account["name"]:
                        continue
                    votes.append(op)
                elif op["type"] == "curation_reward":
                    curation_reward = self.stm.vests_to_sp(
                        Amount(op["reward"], steem_instance=self.stm))
                    daily_curation += curation_reward
                elif op["type"] == "author_reward":
                    sbd_payout = (Amount(op["sbd_payout"],
                                         steem_instance=self.stm))
                    steem_payout = (Amount(op["steem_payout"],
                                           steem_instance=self.stm))
                    sp_payout = self.stm.vests_to_sp(
                        Amount(op["vesting_payout"], steem_instance=self.stm))
                    daily_author_SP += sp_payout
                    daily_author_STEEM += float(steem_payout)
                    daily_author_SBD += float(sbd_payout)

            reward_text = "Curation reward (last 24 h): %.3f HP\n" % daily_curation
            reward_text += "Author reward (last 24 h):\n"
            reward_text += "%.3f HP - %.3f HIVE - %.3f HBD" % (
                daily_author_SP, (daily_author_STEEM), (daily_author_SBD))
            self.text2.setText(reward_text)
示例#5
0
class RedFisher:
    def __init__(self):
        """Initialisation."""

        self.load_settings()
        self.nodes = [
            'https://api.steemit.com', 'https://rpc.buildteam.io',
            'https://api.steem.house', 'https://steemd.steemitdev.com',
            'https://steemd.steemitstage.com', 'https://steemd.steemgigs.org'
        ]
        self.s = Steem(keys=self.posting_key)
        self.s.set_default_nodes(self.nodes)
        self.b = Blockchain(self.s)
        set_shared_steem_instance(self.s)
        self.p = Pool(4)

    def timer_start(self):
        """Set a timer to restart the program at 7pm the next day."""

        # Calculate how many seconds until 7pm tomorrow
        now = datetime.today()
        print(now.day)
        a_time = now.replace(day=now.day + 1, hour=19, minute=0, microsecond=0)
        d_time = a_time - now
        secs = d_time.seconds + 1

        # Reload settings from external file
        self.load_settings()

        # Start the timer
        t = threading.Timer(secs, self.redfisher)
        t.start()
        print('Timer set for ' + str(secs / 3600) + ' hours.')

    def load_settings(self):
        """Load the account requrements from an external file."""

        # Load the external .json
        settings = json.loads(open('settings.json', 'r').read())
        # Import the settings to variables
        self.days = settings['days']
        self.posts_per_week = settings['posts_per_week']
        self.min_sp = settings['min_sp']
        self.max_sv = settings['max_sv']
        self.posting_account = settings['posting_account']
        self.posting_key = settings['posting_key']

        print('settings loaded\ndays: %d\nposts per week: %d\nminimum steem '
              'power: %d' % (self.days, self.posts_per_week, self.min_sp))

    def redfisher(self):
        """
        Streams through all posts within given timeframe and sends accounts to
        be validated.
        """

        t1 = time.process_time()

        # Calculate the start block based on how many days were specified
        # in the settings
        now = datetime.now()
        start_date = now - timedelta(days=self.days)
        start_block = self.b.get_estimated_block_num(start_date)
        # Get the end block
        end_block = self.b.get_current_block_num()

        # Create/reset approved user dictionary
        self.user_list = dict()

        # stream comments from start block to current block
        print('streaming comments now')

        # Create checked accounts list
        checked_accounts = list()

        # Infinite while allows for many node swaps
        while True:
            try:
                # Start/continue the stream from start/lastchecked block
                for post in self.b.stream(opNames=['comment'],
                                          start=start_block,
                                          stop=end_block):
                    # Set start block to the one currently being checked
                    start_block = post['block_num']

                    # Assure that the post is not a comment
                    if post['parent_author'] == '':
                        author = post['author']

                        # Don't check accounts that have already been checked
                        if author not in checked_accounts:
                            # Add account to checked accounts
                            checked_accounts.append(author)
                            # Add account to pool to be checked
                            self.p.enqueue(func=self.check, user=author)
                            self.p.run()

                # All checks completed, break loop
                break

            except Exception as e:
                # Switch nodes
                print(e)
                self.failover()

        time.sleep(1)
        t2 = time.process_time()
        print(t2 - t1)

        # Wait for task pool to empty
        while self.p.done() == False:
            time.sleep(2)

        # Attempt to post every 20 seconds until complete
        while True:
            try:
                self.post()
                break
            except:
                time.sleep(20)

    def get_account_age(self, acc):
        """Calculate how old an account is.
        
        Keyword arguments:
        acc -- the account to be checked -- type: Account
        """

        # Declare account creation types
        types = [
            'create_claimed_account', 'account_create_with_delegation',
            'account_create'
        ]

        # Look through history until account creation is found
        for i in acc.history(only_ops=types):
            # Get account creation timestamp
            creation_date_raw = i['timestamp']
            break
        print(creation_date_raw)

        # Convert timestamp into datetime obj
        creation_date = datetime.strptime(creation_date_raw,
                                          '%Y-%m-%dT%H:%M:%S')

        # Calculate age in days
        now = datetime.now()
        acc_age = (now - creation_date).days

        return acc_age

    def post(self):
        """Make the post containing all the collected info for the round."""

        # Get date in string format
        date = datetime.today().strftime('%Y-%m-%d')
        print(date)

        # Read the post body from external file
        post_body = open('post_body.txt', 'r').read()

        # Order the approved accounts by age
        sorted_ul = sorted(self.user_list.keys(),
                           key=lambda y: (self.user_list[y]['age']))

        # For each approved user, add them to the bottom of the post table
        for username in sorted_ul:
            data = self.user_list[username]
            sp = str(round(data['sp'], 3))
            age = data['age']
            svp = data['svp']
            post_body += '\n@%s | %s | %s | %s' % (username, sp, age, svp)

        print(post_body)

        # Broadcast post transaction
        self.s.post(title='Small Accounts To Support - ' + date,
                    body=post_body,
                    author=self.posting_account,
                    tags=[
                        'onboarding', 'retention', 'steem', 'help',
                        'delegation', 'community', 'giveaway'
                    ])
        print('posted')

        # Reset the cycle
        self.refresh()

    def check(self, user):
        """
        Check that the users meet the requirements.
        
        user -- the account to be checked -- type: Account/str
        """

        # If an account wasn't passed, make str into account
        if type(user) != Account:
            acc = Account(user)

        # Check account steempower
        sp = self.sp_check(acc)
        print(user + " sp == " + str(sp))
        if sp <= float(self.min_sp):
            print('min sp met')

            # Check account posts per week
            ppw_check = self.post_check(acc)
            print(user + " posts per week check == " + str(ppw_check))
            if ppw_check:
                print('posts per week met')

                # Check self vote percent
                self_vote_pct = self.vote_check(acc)
                print(user + ' self votes == %' + str(self_vote_pct))
                if self_vote_pct < self.max_sv:
                    print('self vote check met')

                    # Check for powerups and powerdowns
                    powered_up, powered_down = self.vest_check(acc)
                    print(user + " powered up == " + str(powered_up))
                    print(user + " powered down == " + str(powered_down))
                    if powered_up and not powered_down:
                        print('vest check met')

                        # All checks completed

                        # Get account age
                        age = self.get_account_age(acc)

                        # Add account to list so their data is stored for the
                        # daily post.
                        self.user_list[user] = {
                            'sp': round(sp, 3),
                            'age': age,
                            'svp': round(self_vote_pct, 2)
                        }
                        print(self.user_list)

    def sp_check(self, acc):
        """
        Return the users steem power (ignoring outgoing delegations).
        
        acc -- the account to be checked -- type: Account
        """

        # Get absolute steempower
        sp = float(acc.get_steem_power())

        # Get all outgoing delegations and add them to account sp
        for delegation in acc.get_vesting_delegations():
            vests = float(delegation['vesting_shares']['amount'])
            precision = delegation['vesting_shares']['precision']

            dele_sp_raw = self.s.vests_to_sp(vests)
            dele_sp = dele_sp_raw / 10**precision

            sp += dele_sp

        return sp

    def vest_check(self, acc):
        """Check for opwer ups/downs and return 
        powered_up (bool), powered_down (bool).
        
        acc -- the account to be checked -- type: Account
        """

        # get all time powerup and powerdown history
        powered_up = False
        powered_down = False

        vest_history = acc.history_reverse(
            only_ops=['withdraw_vesting', 'transfer_to_vesting'])
        # check for powerups and powerdowns
        for change in vest_history:
            if change['type'] == 'withdraw_vesting':
                powered_down = True
            if change['type'] == 'transfer_to_vesting':
                powered_up = True

            if powered_up and powered_down:
                break

        return powered_up, powered_down

    def vote_check(self, acc):
        """Return the self vote percentage based on weight.
        
        acc -- the account to be checked -- type: Account
        """

        # Declare variables
        total = 0
        self_vote = 0

        # Date datetime for a week ago
        wa = self._get_date_past()
        # Go through all votes in the past week
        for i in acc.history_reverse(only_ops=['vote'], stop=wa):
            # Update total
            total += int(i['weight'])
            # Update self vote total if self vote
            if i['author'] == i['voter']:
                self_vote += int(i['weight'])

        # No votes made results in /0 error, return 0% self vote
        if total == 0:
            return 0

        self_vote_pct = (self_vote / total) * 100

        return self_vote_pct

    def post_check(self, acc):
        """Return true if posts per week requirement is met, false if not.
        
        acc -- the account to be checked -- type: Account
        """

        # Get datetime for a week ago
        wa = self._get_date_past()
        # Get comment history for the last week
        blog_history = acc.history_reverse(only_ops=['comment'], stop=wa)

        # Count how many posts were made in the last week
        count = 0
        for post in blog_history:
            # Check to make sure it isn't a reply
            if post['parent_author'] == '':
                count += 1

        if self.posts_per_week >= count:
            return True
        return True

    def _get_date_past(self, days_ago=7):
        """Returns the datetime for the current time, x days ago.
        
        days_ago -- how many days ago you want the datetime for -- type: int
        """

        now = datetime.now()
        return now - timedelta(days=days_ago)

    def refresh(self):
        """Called when the main module has finished executing and the post has 
        been made. It resets all the settings and resets the cycle.
        """

        self.user_list = dict()
        self.load_settings()
        self.timer_start()

    def failover(self):
        """Switch/cycle through nodes."""

        self.nodes = self.nodes[1:] + [self.nodes[0]]
        print('Switching nodes to ' + self.nodes[0])
示例#6
0
c_list = []
names=[]
for c in acc.history_reverse(only_ops=["delegate_vesting_shares"]):
    data=re.findall("'delegator': '(.+?)'",str(c)),re.findall("'delegatee': '(.+?)'",str(c)),re.findall("'amount': '(.+?)'",str(c))
    name=re.findall("'delegator': '(.+?)'",str(c))
    if name not in names:
        print(re.findall("'delegator': '(.+?)'",str(c)),re.findall("'delegatee': '(.+?)'",str(c)),re.findall("'amount': '(.+?)'",str(c)))
        c_list.append(data)
        names.append(name)
active=[]
removed=[]
for i in c_list:
    if str(i[2])=="['0']":
        data=i[0][0],i[2][0]
        removed.append(data)
    else:
        hive=stm.vests_to_sp(i[2][0])#.split(' ')[0]))
        data=i[0][0], hive #i[2][0]
        #print ('DATA 2', data)
        active.append(data)
for i in active:
    print (i[0],':',round(i[1]/1000000,3),'HIVE')
print ('ACTIVE:',len(active))
print ('LOST:',len(removed))
a=input ('Do you want to print the undelgator list?')
if a=='y':
    for i in removed:
        print (i[0][0],':',i[1],'HIVE')
else:
    exit
示例#7
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(QMainWindow, self).__init__()
        # Set up the user interface from Designer.
        self.setupUi(self)
        
        self.setAccessibleName("Hive Desktop")
        self.redrawLock = Lock()
        self.updateLock = Lock()
        
        self.optionsDialog = dialogs.Options(self)
        self.aboutDialog = dialogs.About(self,
            copyright='holger80',
            programName='Hive Desktop',
            version=VERSION,
            website='https://github.com/holgern/hivedesktop',
            websiteLabel='Github',
            comments='"Welcome to Hive desktop!\n This is the first release for testing qt5.\n Please vote for holger80 as witness, if you like this :).',
            licenseName='GPL-3.0',
            # licenseUrl=helpers.joinpath_to_cwd('LICENSE').as_uri(),
            authors=('holger80',),
            # dependencies=[l.strip() for l in requirements.readlines()],
        )		
        self.mdrenderer = MDRenderer(str(helpers.joinpath_to_cwd('themes')))

        # tmpfile = helpers.mktemp(prefix='hivedesktop', suffix='.html')
        
        self.post = {"body": "##test", "authorperm": "@test/test"}
        self.thread = threads.MDThread(self)
        
        
        # self.webview.url = tmpfile.as_uri()
        
        
        self.feedListWidget.currentRowChanged.connect(self.change_displayed_post, Qt.QueuedConnection)
        
        self.timer = QTimer()
        self.timer.timeout.connect(self.refresh_account_thread)
        
        self.timer2 = QTimer()
        self.timer2.timeout.connect(self.update_account_hist_thread)

        self.timer3 = QTimer()
        self.timer3.timeout.connect(self.update_account_feed_thread)
        
        self.cache_path = QStandardPaths.writableLocation(QStandardPaths.CacheLocation)
        self.db_type = "shelve"
        self.db_type = "sqlite"
        self.feed = []
        self.post = None
        # Get settings
        settings = QSettings()
        # Get checkbox state with speciying type of checkbox:
        # type=bool is a replacement of toBool() in PyQt5
        check_state = settings.value(SETTINGS_TRAY, True, type=bool)
        hist_info_check_state = settings.value(SETTINGS_HIST_INFO, True, type=bool)
        account_state = settings.value(SETTINGS_ACCOUNT, "", type=str)
        self.resize(settings.value(SETTINGS_SIZE, QSize(1053, 800)))
        self.move(settings.value(SETTINGS_POS, QPoint(50, 50)))
        
        #self.accountHistTableWidget.setColumnCount(5)
        #self.accountHistTableWidget.setHorizontalHeaderLabels(["type", "1", "2", "3", "timestamp"])
        
        self.update_account_refreshtime = 5000
        
        # Set state
        self.accountHistNotificationCheckBox.setChecked(hist_info_check_state)
        self.autoRefreshCheckBox.setChecked(check_state)
        if check_state:
            self.timer.start(self.update_account_refreshtime)
            self.timer2.start(15000)
            self.timer3.start(60000)
        self.accountLineEdit.setText(account_state)
        # connect the slot to the signal by clicking the checkbox to save the state settings
        self.autoRefreshCheckBox.clicked.connect(self.save_check_box_settings)   
        self.accountHistNotificationCheckBox.clicked.connect(self.save_check_box_settings)  
        self.accountLineEdit.editingFinished.connect(self.save_account_settings)
        self.actionAbout.triggered.connect(self.about)
        self.actionOptions.triggered.connect(self.options)
        self.threadpool = QThreadPool()
        
        self.minimizeAction = QAction("Mi&nimize", self, triggered=self.hide)
        self.maximizeAction = QAction("Ma&ximize", self,
                triggered=self.showMaximized)
        self.restoreAction = QAction("&Restore", self,
                triggered=self.showNormal)        
        
        menu = QMenu()
        menu.addAction(self.minimizeAction)
        menu.addAction(self.maximizeAction)
        menu.addAction(self.restoreAction)
        menu.addSeparator()        
        # aboutAction = menu.addAction("about")
        # aboutAction.triggered.connect(self.about)
        exitAction = menu.addAction("Exit")
        exitAction.triggered.connect(self.closeApp)
        
        self.tray = QSystemTrayIcon(QIcon(':/icons/icon.ico'))
        
        self.tray.setContextMenu(menu)
        self.tray.activated.connect(self.trayAction)
        
        self.tray.setToolTip("Hive Desktop!")
        self.tray.setObjectName("Hive Desktop")
        self.setWindowTitle("Hive Desktop")
        self.tray.show()
        
        splash_pix = QPixmap(':/icons/splash.png')
        splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
        splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        splash.setEnabled(False)
        
        #splash.show()
        #splash.showMessage("<h1><font color='green'>starting...</font></h1>", Qt.AlignTop | Qt.AlignCenter, Qt.black)        
        
        account = account_state
        nodelist = NodeList()
        nodelist.update_nodes()
        self.stm = Steem(node=nodelist.get_nodes(hive=True))
        set_shared_blockchain_instance(self.stm)
        if account != "":
            try:
                self.hist_account = Account(account, steem_instance=self.stm)
            except:
                self.hist_account = None
        else:
            self.hist_account = None
            
        self.refreshPushButton.clicked.connect(self.refresh_account)
        self.refreshPushButton.clicked.connect(self.update_account_hist_thread)
        self.accountLineEdit.editingFinished.connect(self.update_account_info)        
        if self.hasFocus is not None:
            self.init_new_account()
            self.init_new_blocks()
        splash.deleteLater()

    def triggeredPreview(self):
        self.authorLabel.setText(self.post["author"])
        self.titleLabel.setText(self.post["title"])
        self.auhorpermLineEdit.setText(construct_authorperm(self.post["author"], self.post["permlink"]))
        self.thread.start()

    @pyqtSlot(str)
    def cbMDThread(self, html):
        self.webview.setHtml(html)

    @pyqtSlot(QSystemTrayIcon.ActivationReason)
    def trayAction(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            if self.isHidden():
                self.showNormal()
            else:
                self.hide()

    def closeEvent(self, event):
        if self.tray.isVisible():
            #QMessageBox.information(self, "Hive Desktop",
            #        "The program will keep running in the system tray. To "
            #        "terminate the program, choose <b>Quit</b> in the "
            #        "context menu of the system tray entry.")
            self.tray.showMessage("Hive Desktop",
                    "The program will keep running in the system tray. To "
                    "terminate the program, choose Quit in the "
                    "context menu of the system tray entry.")           
            self.hide()
            event.ignore()

    def hide(self):
        self.update_account_refreshtime = 60000
        self.timer.start(self.update_account_refreshtime)
        QMainWindow.hide(self)
        

    def showNormal(self):
        self.update_account_refreshtime = 5000
        self.timer.start(self.update_account_refreshtime)
        QMainWindow.showNormal(self)

    def showMaximized(self):
        self.update_account_refreshtime = 5000
        self.timer.start(self.update_account_refreshtime)
        QMainWindow.showMaximized(self)

    def closeApp(self):
        settings = QSettings()
        settings.setValue(SETTINGS_SIZE, self.size())
        settings.setValue(SETTINGS_POS, self.pos())
        settings.sync()
        sys.exit()

    def about(self):
        self.aboutDialog.exec_()

    def options(self):
        self.optionsDialog.exec_()

    # Slot checkbox to save the settings
    def save_check_box_settings(self):
        settings = QSettings()
        settings.setValue(SETTINGS_HIST_INFO, self.accountHistNotificationCheckBox.isChecked())
        settings.setValue(SETTINGS_TRAY, self.autoRefreshCheckBox.isChecked())
        if self.autoRefreshCheckBox.isChecked():
            self.timer.start(self.update_account_refreshtime)
            self.timer2.start(15000)
            self.timer3.start(60000)
        else:
            self.timer.stop()
            self.timer2.stop()
            self.timer3.stop()
        settings.sync()

    # Slot checkbox to save the settings
    def save_account_settings(self):
        settings = QSettings()
        settings.setValue(SETTINGS_ACCOUNT, self.accountLineEdit.text())
        settings.sync()

    def update_account_info(self):
        if self.hist_account is None or self.hist_account["name"] != self.accountLineEdit.text():
            try:
                self.hist_account = Account(self.accountLineEdit.text(), steem_instance=self.stm)
            except:
                self.hist_account = None
            self.init_new_account()

    def init_new_account(self):
        self.refresh_account()
        self.update_account_feed()
        if self.hist_account is not None:
            self.db = database.Database(self.db_type, self.cache_path, self.hist_account["name"])
            self.loadingProgressBar.setMaximum(self.db.get_account().virtual_op_count())
            self.iah_thread = threads.IAHThread(self, self.db)
            self.timer.stop()
            self.timer2.stop()
            self.refreshPushButton.setEnabled(False)
            self.accountLineEdit.setEnabled(False)            
            self.iah_thread.start()
        else:
            self.init_account_hist()
            self.update_account_hist()

    def init_new_blocks(self):
        blockchain = Blockchain()
        self.block_db = database_blocks.DatabaseBlocks(self.db_type, self.cache_path)
        self.loadingBlocksProgressBar.setMaximum(self.block_db.block_history)
        self.blocks_thread = threads.BlocksThread(self, self.block_db, blockchain)
        self.blocks_thread.start()

    @pyqtSlot(str)
    def cIAHThread(self, dummy):
        self.init_account_hist()
        self.update_account_hist()
        self.refreshPushButton.setEnabled(True)
        self.accountLineEdit.setEnabled(True)
        self.tray.showMessage("Ready", "Account history loaded!")     
        self.timer.start(self.update_account_refreshtime)
        self.timer2.start(15000)

    @pyqtSlot(str)
    def cBlocksThread(self, dummy):
        self.init_blocks()
        self.update_blocks()
           
        #self.timer.start(self.update_account_refreshtime)
        #self.timer2.start(15000)

    def refresh_account_thread(self):
        worker = Worker(self.refresh_account)
        self.threadpool.start(worker)        

    def refresh_account(self):
        if self.hist_account is None:
            return
        self.hist_account.refresh()
        self.accountInfoGroupBox.setTitle("%s (%.3f)" % (self.hist_account["name"], self.hist_account.rep))
        with self.redrawLock:
            self.votePowerProgressBar.setValue(int(self.hist_account.vp))
            if self.hist_account.vp == 100:
                self.votePowerProgressBar.setFormat("%.2f %%" % (self.hist_account.vp))
            else:
                self.votePowerProgressBar.setFormat("%.2f %%, full in %s" % (self.hist_account.vp, self.hist_account.get_recharge_time_str()))
        down_vp = self.hist_account.get_downvoting_power()
        with self.redrawLock:
            self.downvotePowerProgressBar.setValue(int(down_vp))
            if down_vp == 100:
                self.downvotePowerProgressBar.setFormat("%.2f %%" % (down_vp))
            else:
                self.downvotePowerProgressBar.setFormat("%.2f %%, full in %s" % (down_vp, self.hist_account.get_recharge_time(starting_voting_power=down_vp)))
        
        self.votePowerLabel.setText("Vote Power, a 100%% vote is %.3f $" % (self.hist_account.get_voting_value_SBD()))
        self.downvotePowerLabel.setText("DownVote Power")
        self.STEEMLabel.setText(str(self.hist_account["balance"]))
        self.SBDLabel.setText(str(self.hist_account["sbd_balance"]))
        self.SPLabel.setText("%.3f HP" % self.stm.vests_to_sp(self.hist_account["vesting_shares"]))
        try:
            rc_manabar = self.hist_account.get_rc_manabar()
            with self.redrawLock:
                self.RCProgressBar.setValue(int(rc_manabar["current_pct"]))
                self.RCProgressBar.setFormat("%.2f %%, full in %s" % (rc_manabar["current_pct"], self.hist_account.get_manabar_recharge_time_str(rc_manabar)))
        
            rc = self.hist_account.get_rc()
            estimated_rc = int(rc["max_rc"]) * rc_manabar["current_pct"] / 100
            rc_calc = RC(steem_instance=self.stm)
            self.RCLabel.setText("RC (%.0f G RC of %.0f G RC)" % (estimated_rc / 10**9, int(rc["max_rc"]) / 10**9))
            ret = "--- Approx Costs ---\n"
            ret += "comment - %.2f G RC - enough RC for %d comments\n" % (rc_calc.comment() / 10**9, int(estimated_rc / rc_calc.comment()))
            ret += "vote - %.2f G RC - enough RC for %d votes\n" % (rc_calc.vote() / 10**9, int(estimated_rc / rc_calc.vote()))
            ret += "transfer - %.2f G RC - enough RC for %d transfers\n" % (rc_calc.transfer() / 10**9, int(estimated_rc / rc_calc.transfer()))
            ret += "custom_json - %.2f G RC - enough RC for %d custom_json\n" % (rc_calc.custom_json() / 10**9, int(estimated_rc / rc_calc.custom_json()))
            self.text.setText(ret)
        except:
            rc_manabar = None

    @pyqtSlot(int)
    def set_loading_progress(self, val):
        with self.redrawLock:
            self.loadingProgressBar.setValue(val)

    @pyqtSlot(int)
    def set_loading_blocks_progress(self, val):
        with self.redrawLock:
            self.loadingBlocksProgressBar.setValue(val)

    def init_blocks(self):
        self.blockCountLabel.setText("%d entries" % self.block_db.get_block_count())

    def init_account_hist(self):
        if self.hist_account is None:
            return
        self.account_hist_info = {"start_block": 0}
        self.append_hist_info = {"start_block": 0}

        #if not self.db.has_account_hist():
        #    ops = self.db.get_acc_hist()
        #    self.db.store_account_hist(ops)
        #else:
        #    start_op = self.db.get_last_op()
        #    ops = self.db.read_missing_account_history_data(start_op)
        #    self.db.store_account_hist(ops)
        self.accountHistoryLabel.setText("%d entries" % self.db.get_count())
        self.accountHistTableWidget.clear()

    def append_blocks(self):
        start_op = self.block_db.get_last_op()
        data = self.block_db.read_missing_block_data(start_op)
        # print("finished")
        if len(data) > 0:
            # print(op["timestamp"])
            self.block_db.append_blocks(data)
            self.blockCountLabel.setText("%d entries" % self.block_db.get_block_count())        

    def append_account_hist(self):
        if self.hist_account is None:
            return
        
        # print("loading db")
        
        start_op = self.db.get_last_op()
        data = self.db.read_missing_account_history_data(start_op)
        # print("finished")
        if len(data) > 0:
            # print(op["timestamp"])
            self.db.append_account_hist(data)
            self.accountHistoryLabel.setText("%d entries" % self.db.get_count())

    def update_account_hist_thread(self):
        worker = Worker(self.update_account_hist)
        self.threadpool.start(worker)

    def update_account_feed_thread(self):
        worker = Worker(self.update_account_feed)
        self.threadpool.start(worker)

    @pyqtSlot(int)
    def change_displayed_post(self, row):
        if row < 0:
            return
        if len(self.feed) == 0:
            return
        if len(self.feed) <= row:
            return
        #index = self.feedListWidget.currentIndex()
        #row = index.row()
        self.post = self.feed[row]
        with self.updateLock:
            self.triggeredPreview()
        replies = Comment(self.post).get_all_replies()
        is_shown = [0] * len(replies)
        max_depth = 0
        for i in range(len(replies)):
            if replies[i].depth > max_depth:
                max_depth = replies[i].depth
        self.commentsTreeWidget.clear()
        
        def create_item(reply):
            item = QTreeWidgetItem()
            item.setText(0, reply["author"])
            item.setText(1, reply["body"])
            item.setToolTip(1, reply["body"])
            return item

      
        for i in range(len(replies)):
            if is_shown[i] == 1:
                continue
            reply = replies[i]
            if reply.depth == 1:
                is_shown[i] = 1
                item = create_item(reply)
                
                for j in range(len(replies)):
                    rr = replies[j]
                    if is_shown[j] == 1:
                        continue
                    if rr.depth == 2:
                        is_shown[j] = 1
                        if rr.parent_author == reply["author"] and rr.parent_permlink == reply["permlink"]:
                            rr_item = create_item(rr)
                            if max_depth >= 3:
                                for k in range(len(replies)):
                                    rrr = replies[k]
                                    if is_shown[k] == 1:
                                        continue
                                    if rrr.depth == 3:
                                        is_shown[k] = 1
                                        if rrr.parent_author == rr["author"] and rrr.parent_permlink == rr["permlink"]:
                                            rrr_item = create_item(rrr)
                                            if max_depth >= 4:
                                                for l in range(len(replies)):
                                                    rrrr = replies[l]
                                                    if is_shown[l] == 1:
                                                        continue
                                                    if rrrr.depth == 4:
                                                        is_shown[l] = 1
                                                        if rrrr.parent_author == rrr["author"] and rrrr.parent_permlink == rrr["permlink"]:
                                                            rrrr_item = create_item(rrrr)
                                                            rrr_item.addChild(rrrr_item)
                                        
                                        rr_item.addChild(rrr_item)
                            item.addChild(rr_item)
                
                self.commentsTreeWidget.addTopLevelItem(item)

    def update_account_feed(self):
        if self.hist_account is None:
            return
        try:
            updated_feed = self.hist_account.get_account_posts()
        except:
            print("could not update feed")
            return
        if len(self.feed) == 0:
            self.feed = updated_feed
        else:
            for post in updated_feed[::-1]:
                found = False
                for p in self.feed:
                    if post["authorperm"] == p["authorperm"]:
                        found = True
                if not found:
                    self.feed.insert(0, post)
                    if (addTzInfo(datetime.utcnow()) - post["created"]).total_seconds() / 60 < 5:
                        self.tray.showMessage(post["author"], post["title"])
        with self.updateLock:
            if self.post is None:
                self.post = self.feed[0]
                self.triggeredPreview()

            self.feedListWidget.currentRowChanged.disconnect(self.change_displayed_post)
            self.feedListWidget.clear()
            for post in self.feed[::-1]:
                post_text = "%s - %s" % (post["author"], post["title"])
                post_item = QListWidgetItem()
                post_item.setText(post_text)
                post_item.setToolTip(post["author"])
                self.feedListWidget.insertItem(0, post_item)   
            self.feedListWidget.currentRowChanged.connect(self.change_displayed_post, Qt.QueuedConnection)

    def update_blocks(self):
        return

    def update_account_hist(self):
        if self.hist_account is None:
            return        
        votes = []
        daily_curation = 0
        daily_author_SP = 0
        daily_author_SBD = 0
        daily_author_STEEM = 0
        self.append_account_hist()
        
        new_op_found = False
        
        start_block = self.account_hist_info["start_block"]
        if start_block == 0:
            first_call = True
            b = Blockchain()
            start_block = b.get_current_block_num() - 20 * 60 * 24 * 7
            self.account_hist_info["start_block"] = start_block
        else:
            first_call = False

        ops = self.db.load_account_hist(start_block)
     
        for op in ops:
            if op["block"] < start_block:
                # last_block = op["block"]
                continue

            start_block = op["block"]
            new_op_found = True
            tray_item = None
            op_timedelta = formatTimedelta(addTzInfo(datetime.utcnow()) - addTzInfo(op["timestamp"]))
            op_local_time = addTzInfo(op["timestamp"]).astimezone(tz.tzlocal())
            # print("Read %d" % op["index"])
            self.accountHistTableWidget.insertRow(0)
            self.accountHistTableWidget.setItem(0, 4, QTableWidgetItem(str(op_local_time)))
            if op["type"] == "vote":
                
                
                if op["voter"] == self.hist_account["name"]:
                    self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem("Vote"))
                    self.accountHistTableWidget.setItem(0, 1, QTableWidgetItem(op["author"]))
                    
                elif op["weight"] >= 0:
                    self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem("Vote Post"))
                    self.accountHistTableWidget.setItem(0, 1, QTableWidgetItem(op["voter"]))
                    tray_item = "%s - %s (%.2f %%) vote %s" % (op["type"], op["voter"], op["weight"] / 100, op["permlink"])
                else:
                    self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem("Dowvote Post"))
                    self.accountHistTableWidget.setItem(0, 1, QTableWidgetItem(op["voter"]))
                    # hist_item.setToolTip(0, op["permlink"])
                    tray_item = "%s - %s (%.2f %%) downvote %s" % (op["type"], op["voter"], op["weight"] / 100, op["permlink"])
                
                
                self.accountHistTableWidget.setItem(0, 2, QTableWidgetItem("%.2f %%" % (op["weight"] / 100)))
                
            elif op["type"] == "curation_reward":
                self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(op["type"]))
                
                curation_reward = self.stm.vests_to_sp(Amount(op["reward"], steem_instance=self.stm))
                self.accountHistTableWidget.setItem(0, 1, QTableWidgetItem("%.3f HP" % curation_reward))
                self.accountHistTableWidget.setItem(0, 2, QTableWidgetItem(construct_authorperm(op["comment_author"], op["comment_permlink"])))
                hist_item = "%s - %s - %.3f HP for %s" % (op_local_time, op["type"], curation_reward, construct_authorperm(op["comment_author"], op["comment_permlink"]))
                tray_item = "%s - %.3f HP for %s" % (op["type"], curation_reward, construct_authorperm(op["comment_author"], op["comment_permlink"]))
            elif op["type"] == "author_reward":
                self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(op["type"]))
                sbd_payout = (Amount(op["sbd_payout"], steem_instance=self.stm))
                steem_payout = (Amount(op["steem_payout"], steem_instance=self.stm))
                sp_payout = self.stm.vests_to_sp(Amount(op["vesting_payout"], steem_instance=self.stm))
                
                hist_item = "%s - %s - %s %s %.3f SP for %s" % (op_local_time, op["type"], str(sbd_payout), str(steem_payout), sp_payout, op["permlink"])
                tray_item = "%s - %s %s %.3f SP for %s" % (op["type"], str(sbd_payout), str(steem_payout), sp_payout, op["permlink"])
            elif op["type"] == "custom_json":
                self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(op["type"]))
                self.accountHistTableWidget.setItem(0, 1, QTableWidgetItem(op["json_id"]))
                json_data = QTableWidgetItem(op["json"])
                json_data.setToolTip(op["json"])
                self.accountHistTableWidget.setItem(0, 2, json_data)
                hist_item = "%s - %s - %s" % (op_local_time, op["type"], op["id"])
                tray_item = "%s - %s" % (op["type"], op["json_id"])
            elif op["type"] == "transfer":
                self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(op["type"]))
                hist_item = "%s - %s - %s from %s" % (op_local_time, op["type"], str(Amount(op["amount"], steem_instance=self.stm)), op["from"])
                tray_item = "%s - %s from %s" % (op["type"], str(Amount(op["amount"], steem_instance=self.stm)), op["from"])
            elif op["type"] == "comment":
                
                
                if op["parent_author"] != "":
                    comment_type = "comment"
                    hist_item = "%s - comment on %s - %s from %s" % (op_local_time, construct_authorperm(op["parent_author"], op["parent_permlink"]), op["title"], op["author"])
                    tray_item = "comment from %s: %s on %s" % (op["author"], op["body"][:100], op["title"])
                    self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(op["type"]))
                    self.accountHistTableWidget.setItem(0, 1, QTableWidgetItem(op["author"]))
                    body = QTableWidgetItem(op["body"])
                    body.setToolTip(op["body"])
                    self.accountHistTableWidget.setItem(0, 2, body)
                else:
                    comment_type = "post"
                    hist_item = "%s - post - %s from %s" % (op_local_time, op["title"], op["author"])
                    tray_item = "post from %s: %s" % (op["author"], op["title"])
                self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(comment_type))
            elif op["type"] == "producer_reward":
                self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(op["type"]))
                self.accountHistTableWidget.setItem(0, 1, QTableWidgetItem(" %.3f HP" % float(self.stm.vests_to_sp(Amount(op["vesting_shares"])))))
                hist_item = "%s - %s" % (op_local_time, op["type"])
                tray_item = "%s - %.3f HP" % (op["type"], float(self.stm.vests_to_sp(Amount(op["vesting_shares"]))))               
            else:
                self.accountHistTableWidget.setItem(0, 0, QTableWidgetItem(op["type"]))
                hist_item = "%s - %s" % (op_local_time, op["type"])
                tray_item = "%s" % (op["type"])
            
            if self.accountHistNotificationCheckBox.isChecked() and not first_call and tray_item is not None:
                self.tray.showMessage(self.hist_account["name"], tray_item)

        if new_op_found:
            self.account_hist_info["start_block"] = start_block
            
            for op in ops:
                if op["type"] == "vote":
                    if op["voter"] == self.hist_account["name"]:
                        continue
                    votes.append(op)
                elif op["type"] == "curation_reward":
                    curation_reward = self.stm.vests_to_sp(Amount(op["reward"], steem_instance=self.stm))
                    daily_curation += curation_reward
                elif op["type"] == "author_reward":
                    sbd_payout = (Amount(op["sbd_payout"], steem_instance=self.stm))
                    steem_payout = (Amount(op["steem_payout"], steem_instance=self.stm))
                    sp_payout = self.stm.vests_to_sp(Amount(op["vesting_payout"], steem_instance=self.stm))
                    daily_author_SP += sp_payout
                    daily_author_STEEM += float(steem_payout)
                    daily_author_SBD += float(sbd_payout)        
        
            
            reward_text = "Curation reward (last 24 h): %.3f HP\n" % daily_curation
            reward_text += "Author reward (last 24 h):\n"
            reward_text += "%.3f HP - %.3f HIVE - %.3f HBD" % (daily_author_SP, (daily_author_STEEM), (daily_author_SBD))
            self.text2.setText(reward_text)