예제 #1
0
    def get_balances(self):
        available = {
            'GOLOS': Amount(self['balance']).amount,
            'GBG': Amount(self['sbd_balance']).amount,
            'GESTS': Amount(self['vesting_shares']).amount,
        }

        savings = {
            'GOLOS': Amount(self['savings_balance']).amount,
            'GBG': Amount(self['savings_sbd_balance']).amount,
        }

        totals = {
            'GOLOS': sum([available['GOLOS'], savings['GOLOS']]),
            'GBG': sum([available['GBG'], savings['GBG']]),
            'GESTS': sum([available['GESTS']]),
        }

        total = walk_values(rpartial(round, 3), totals)

        return {
            'available': available,
            'savings': savings,
            'total': total,
        }
예제 #2
0
def estimate_median_price(steemd_instance, verbose=False):
    """ Calculate new expected median price based on current price feeds
        :param Steem steemd_instance: Steem() instance to use when accesing a RPC
        :param bool verbose: print witnesses sorted by price feed
    """
    count = 21
    try:
        witnesses = steemd_instance.get_witnesses_by_vote('', count)
    except Exception as e:
        log.error(e)
        return False

    # add price key
    for w in witnesses:
        base = Amount(w['sbd_exchange_rate']['base']).amount
        quote = Amount(w['sbd_exchange_rate']['quote']).amount
        w['price'] = base / quote

    # sort witnesses by price
    sorted_w = sorted(witnesses, key=lambda k: k['price'])

    if verbose:
        for w in sorted_w:
            print('{}: {:.3f}'.format(w['owner'], w['price']))

    # 11th element price
    return sorted_w[10]['price']
예제 #3
0
    def curation_stats(self):
        trailing_24hr_t = time.time() - datetime.timedelta(
            hours=24).total_seconds()
        trailing_7d_t = time.time() - datetime.timedelta(
            days=7).total_seconds()

        reward_24h = 0.0
        reward_7d = 0.0

        for reward in take(5000,
                           self.history_reverse(filter_by="curation_reward")):

            timestamp = parse_time(reward["timestamp"]).timestamp()
            if timestamp > trailing_7d_t:
                reward_7d += Amount(reward["reward"]).amount

            if timestamp > trailing_24hr_t:
                reward_24h += Amount(reward["reward"]).amount

        reward_7d = self.converter.vests_to_sp(reward_7d)
        reward_24h = self.converter.vests_to_sp(reward_24h)
        return {
            "24hr": reward_24h,
            "7d": reward_7d,
            "avg": reward_7d / 7,
        }
예제 #4
0
 def steem_per_mvests(self):
     """ Obtain STEEM/MVESTS ratio
     """
     info = self.steemd.get_dynamic_global_properties()
     return (
         Amount(info["total_vesting_fund_steem"]).amount /
         (Amount(info["total_vesting_shares"]).amount / 1e6)
     )
예제 #5
0
 def sbd_median_price(self):
     """ Obtain the sbd price as derived from the median over all
         witness feeds. Return value will be SBD
     """
     return (Amount(self.steemd.get_feed_history()['current_median_history']
                    ['base']).amount /
             Amount(self.steemd.get_feed_history()['current_median_history']
                    ['quote']).amount)
예제 #6
0
    def estimate_median_price(self) -> float:
        """Calculate new expected median price based on last median price feed."""

        last_feed = self.get_feed_history()['price_history'][-1]

        base = Amount(last_feed['base']).amount
        quote = Amount(last_feed['quote']).amount
        price = base / quote

        return price
예제 #7
0
    def get_min_price(self) -> float:
        """Get GBG/GOLOS minimal price (limit by chain)."""

        props = self.get_dynamic_global_properties()
        sbd_supply = Amount(props['current_sbd_supply'])
        current_supply = Amount(props['current_supply'])

        # libraries/chain/database.cpp
        # this min_price caps system debt to 10% of GOLOS market capitalisation
        min_price = 9 * sbd_supply.amount / current_supply.amount

        return min_price
예제 #8
0
def estimate_median_price_from_feed(steemd_instance):
    """ Calculate new expected median price based on last median price feed
        :param Steem steemd_instance: Steem() instance to use when accesing a RPC
    """

    last_feed = steemd_instance.get_feed_history()['price_history'][-1:]

    base = Amount(last_feed[0]['base'])
    quote = Amount(last_feed[0]['quote'])

    median = base.amount / quote.amount
    return median
예제 #9
0
def main(ctx):
    """Show pricefeed history."""

    hist = ctx.helper.get_feed_history()['price_history']
    hist_size = len(hist)

    # median history contains values for STEEMIT_FEED_HISTORY_WINDOW
    # median price update performed once per hour
    for i in hist:
        timestamp = datetime.now() - timedelta(hours=hist_size)
        base = Amount(i['base'])
        quote = Amount(i['quote'])
        price = base.amount / quote.amount
        print('{}: {:.3f}'.format(timestamp.strftime('%d.%m.%Y %H'), price))
        # use hist_size as iterator
        hist_size -= 1
예제 #10
0
def main():

    parser = argparse.ArgumentParser(
        description='Scan account history looking for transfers',
        epilog='Report bugs to: https://github.com/bitfag/golos-scripts/issues'
    )
    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='enable debug output'),
    parser.add_argument('-c',
                        '--config',
                        default='./common.yml',
                        help='specify custom path for config file')
    parser.add_argument(
        '-a',
        '--amount',
        type=float,
        default=0,
        help='minimal transfer amount to look for (default: 0)')
    parser.add_argument(
        '-l',
        '--limit',
        type=int,
        default=50,
        help='limit number of transactions to scan, default: 50')
    parser.add_argument('account', help='account to scan')
    args = parser.parse_args()

    # create logger
    if args.debug == True:
        log.setLevel(logging.DEBUG)
    else:
        log.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s")
    handler.setFormatter(formatter)
    log.addHandler(handler)

    # parse config
    with open(args.config, 'r') as ymlfile:
        conf = yaml.load(ymlfile)

    golos = Steem(nodes=conf['nodes_old'], keys=conf['keys'])

    account = Account(args.account, steemd_instance=golos)
    history = account.rawhistory(only_ops=['transfer'], limit=args.limit)

    for item in history:
        #pprint(item)

        timestamp = datetime.strptime(item[1]['timestamp'],
                                      '%Y-%m-%dT%H:%M:%S')
        t_from = item[1]['op'][1]['from']
        to = item[1]['op'][1]['to']
        amount = Amount(item[1]['op'][1]['amount'])

        if amount.amount > args.amount:
            print('{}: {:<16} -> {:<16}, {}'.format(timestamp, t_from, to,
                                                    amount))
예제 #11
0
def calc_payout(steemd_instance, net_rshares, curve='linear'):
    """ Calc payout in GOLOS based on net_rshares
        https://golos.io/ru--apvot50-50/@now/kak-na-samom-dele-rabotayut-kvadratichnye-nachisleniya-golosa-2kh-50-50
        :param Steem steemd_instance: Steem() instance to use when accesing a RPC
        :param int net_rshares: net_rshares to calculate payout from
        :param str curve: reward curve
        :return float payout: payout amount in GOLOS
    """

    try:
        global_props = steemd_instance.get_dynamic_global_properties()
    except Exception as e:
        log.error(e)
        return False

    if curve == 'quadratic':
        # perform same calculations as golosd v0.16.4
        # c++ code: return (rshares + s) * (rshares + s) - s * s;
        vshares = (net_rshares + CONTENT_CONSTANT) * (
            net_rshares + CONTENT_CONSTANT) - CONTENT_CONSTANT**2
    elif curve == 'linear':
        vshares = net_rshares

    total_reward_fund_steem = Amount(global_props['total_reward_fund_steem'])
    total_reward_shares2 = int(global_props['total_reward_shares2'])
    payout = vshares * total_reward_fund_steem.amount / total_reward_shares2
    log.debug('calculated post payout, GOLOS: {:.8f}'.format(payout))
    return payout
예제 #12
0
    def refresh(self):
        post_author, post_permlink = resolve_identifier(self.identifier)
        post = self.steemd.get_content(post_author, post_permlink)
        if not post["permlink"]:
            raise PostDoesNotExist("Post does not exist: %s" % self.identifier)

        # If this 'post' comes from an operation, it might carry a patch
        if "body" in post and re.match("^@@", post["body"]):
            self.patched = True

        # TODO: Check
        # This field is returned from blockchain, but it's empty. Fill it
        post['reblogged_by'] = [i for i in self.steemd.get_reblogged_by(post_author, post_permlink) if i != post_author]

        # Parse Times
        parse_times = ["active",
                       "cashout_time",
                       "created",
                       "last_payout",
                       "last_update",
                       "max_cashout_time"]
        for p in parse_times:
            post[p] = parse_time(post.get(p, "1970-01-01T00:00:00"))

        # Parse Amounts
        sbd_amounts = [
            'total_payout_value',
            'max_accepted_payout',
            'pending_payout_value',
            'curator_payout_value',
            'total_pending_payout_value',
            'promoted',
        ]
        for p in sbd_amounts:
            post[p] = Amount(post.get(p, "0.000 GBG"))

        # calculate trending and hot scores for sorting
        post['score_trending'] = calculate_trending(post.get('net_rshares', 0), post['created'])
        post['score_hot'] = calculate_hot(post.get('net_rshares', 0), post['created'])

        # turn json_metadata into python dict
        meta_str = post.get("json_metadata", "{}")
        post['json_metadata'] = silent(json.loads)(meta_str) or {}

        post["tags"] = []
        post['community'] = ''
        if isinstance(post['json_metadata'], dict):
            if post["depth"] == 0:
                tags = [post["parent_permlink"]]
                tags += get_in(post, ['json_metadata', 'tags'], default=[])
                tags_set = set(tags)
                post["tags"] = [tag for tag in tags if tag not in tags_set]

            post['community'] = get_in(post, ['json_metadata', 'community'], default='')

        # If this post is a comment, retrieve the root comment
        self.root_identifier, self.category = self._get_root_identifier(post)

        self._store_post(post)
예제 #13
0
    def get_witness_pricefeed(self, witness: Union[str, Dict]) -> float:
        """Obtain current published price for single witness."""

        if isinstance(witness, str):
            witness_data = Witness(witness)
        else:
            witness_data = witness
        base = Amount(witness_data['sbd_exchange_rate']['base']).amount
        quote = Amount(witness_data['sbd_exchange_rate']['quote']).amount

        # whether witness not exists yet, return 0
        if quote == 0:
            return 0

        price = base / quote

        return price
def main(ctx, min_mgests, account):
    """Find all vesting withdrawals with rates and dates."""

    ctx.log.debug('total accounts: %s', ctx.helper.get_account_count())

    if account:
        accs = [account]
    else:
        accs = ctx.helper.get_all_usernames()

    start = datetime.utcnow()

    # get all accounts in one batch
    all_accounts = ctx.helper.get_accounts(accs)

    # we well get summary info about total withdrawal rate and number of accounts
    sum_rate = float()
    count = int()

    cv = ctx.helper.converter
    steem_per_mvests = cv.steem_per_mvests()

    for acc in all_accounts:
        vshares = Amount(acc['vesting_shares'])
        mgests = vshares.amount / 1000000
        rate = Amount(acc['vesting_withdraw_rate'])
        date = parse_time(acc['next_vesting_withdrawal'])

        if mgests > min_mgests and rate.amount > 1000:
            # We use own calculation instead of cv.vests_to_sp() to speed up execution
            # avoiding API call on each interation
            rate_gp = rate.amount / 1e6 * steem_per_mvests
            gp = vshares.amount / 1e6 * steem_per_mvests
            sum_rate += rate_gp
            count += 1

            print('{:<16} {:<18} {:>6.0f} {:>8.0f}'.format(
                acc['name'], date.strftime('%Y-%m-%d %H:%M'), rate_gp, gp))

    ctx.log.debug('accounts iteration took {:.2f} seconds'.format(
        (datetime.utcnow() - start).total_seconds()))

    ctx.log.info(
        'numbers of matching accounts on vesting withdrawal: {}'.format(count))
    ctx.log.info('sum rate: {:.0f}'.format(sum_rate))
예제 #15
0
def main(ctx, gests, from_, to, amount):

    if gests:
        gests = amount
    else:
        cv = ctx.helper.converter
        gests = cv.sp_to_vests(amount)

    gests = Amount('{} GESTS'.format(gests))
    ctx.helper.delegate_vesting_shares(to, gests, account=from_)
예제 #16
0
    def get_price_feeds(self) -> List[feed]:
        """Get current price feeds as reported by witnesses."""
        witnesses = self.get_active_witnesses()
        witnesses = [Witness(i) for i in witnesses]

        # add price key
        for i in witnesses:
            base = Amount(i['sbd_exchange_rate']['base']).amount
            quote = Amount(i['sbd_exchange_rate']['quote']).amount
            try:
                i['price'] = base / quote
            except ZeroDivisionError:
                pass

        feeds = [
            feed(i['owner'], i['price']) for i in witnesses if 'price' in i
        ]
        feeds = sorted(feeds, key=lambda k: k.price)

        return feeds
예제 #17
0
파일: dex.py 프로젝트: Chainers/steep-golos
    def get_ticker(self):
        """ Returns the ticker for all markets.

            Output Parameters:

            * ``latest``: Price of the order last filled
            * ``lowest_ask``: Price of the lowest ask
            * ``highest_bid``: Price of the highest bid
            * ``sbd_volume``: Volume of SBD
            * ``steem_volume``: Volume of STEEM
            * ``percent_change``: 24h change percentage (in %)

            .. note::

                Market is STEEM:SBD and prices are SBD per STEEM!

            Sample Output:

            .. code-block:: js

                 {'highest_bid': 0.30100226633322913,
                  'latest': 0.0,
                  'lowest_ask': 0.3249636958897082,
                  'percent_change': 0.0,
                  'sbd_volume': 108329611.0,
                  'steem_volume': 355094043.0}


        """
        t = self.steemd.get_ticker()
        return {
            'highest_bid': float(t['highest_bid']),
            'latest': float(t["latest"]),
            'lowest_ask': float(t["lowest_ask"]),
            'percent_change': float(t["percent_change"]),
            'sbd_volume': Amount(t["sbd_volume"]),
            'steem_volume': Amount(t["steem_volume"])
        }
예제 #18
0
def main(ctx, account):
    """Calculate profit from vesting holdings."""
    props = ctx.helper.get_dynamic_global_properties()
    acc = Account(account)
    balance = acc.get_balances()
    account_vesting = balance['total']['GESTS']
    vesting_fund = Amount(props['total_vesting_shares'])

    daily_emission = ctx.helper.calc_inflation()
    vesting_share = account_vesting / vesting_fund.amount
    ctx.log.info(f'{account} vesting share: {vesting_share:.4%}')

    daily_account_vesting = vesting_share * daily_emission.vesting
    ctx.log.info(f'{account} daily vesting: {daily_account_vesting:.0f}')
예제 #19
0
    def sbd_to_rshares(self, sbd_payout):
        """ Obtain r-shares from SBD

            :param number sbd_payout: Amount of SBD
        """
        steem_payout = self.sbd_to_steem(sbd_payout)

        props = self.steemd.get_dynamic_global_properties()
        total_reward_fund_steem = Amount(props['total_reward_fund_steem'])
        total_reward_shares2 = int(props['total_reward_shares2'])

        post_rshares2 = (steem_payout / total_reward_fund_steem) * total_reward_shares2

        rshares = math.sqrt(self.CONTENT_CONSTANT ** 2 + post_rshares2) - self.CONTENT_CONSTANT
        return rshares
예제 #20
0
def main(ctx, amount_limit, limit, account):
    """Scan account history looking for transfers."""

    account = Account(account)
    history = account.rawhistory(only_ops=['transfer'], limit=limit)

    for item in history:
        ctx.log.debug(pformat(item))

        timestamp = parse_time(item[1]['timestamp'])
        from_ = item[1]['op'][1]['from']
        to = item[1]['op'][1]['to']
        amount = Amount(item[1]['op'][1]['amount'])
        memo = item[1]['op'][1]['memo']

        if amount.amount > amount_limit:
            print('{}: {:<16} -> {:<16}, {}, {}'.format(timestamp, from_, to, amount, memo))
예제 #21
0
def typify(value: Union[dict, list, set, str]):
    """ Enhance block operation with native types.

    Typify takes a blockchain operation or dict/list/value,
    and then it parses and converts string types into native data types where appropriate.
    """
    if type(value) == dict:
        return walk_values(typify, value)

    if type(value) in [list, set]:
        return list(map(typify, value))

    if type(value) == str:
        if re.match('^\d+\.\d+ (GOLOS|GBG|GESTS)$', value):
            return keep_in_dict(dict(Amount(value)), ['amount', 'asset'])

        if re.match('^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$', value):
            return parse_time(value)

    return value
예제 #22
0
    def get_balances(self):
        available = {
            "GOLOS": Amount(self["balance"]).amount,
            "GBG": Amount(self["sbd_balance"]).amount,
            "GESTS": Amount(self["vesting_shares"]).amount,
        }

        savings = {
            "GOLOS": Amount(self["savings_balance"]).amount,
            "GBG": Amount(self["savings_sbd_balance"]).amount,
        }

        accumulative = {"GOLOS": Amount(self["accumulative_balance"]).amount}

        tip = {"GOLOS": Amount(self["tip_balance"]).amount}

        totals = {
            "GOLOS":
            sum([
                available["GOLOS"], savings["GOLOS"], accumulative["GOLOS"],
                tip["GOLOS"]
            ]),
            "GBG":
            sum([available["GBG"], savings["GBG"]]),
            "GESTS":
            sum([available["GESTS"]]),
        }

        total = walk_values(rpartial(round, 3), totals)

        return {
            "available": available,
            "savings": savings,
            "accumulative": accumulative,
            "tip": tip,
            "total": total,
        }
예제 #23
0
 def reward(self):
     """Return a float value of estimated total SBD reward.
     """
     return Amount(self.get("total_payout_value", "0 SBD")) + \
            Amount(self.get("pending_payout_value", "0 SBD"))
예제 #24
0
def test_amount_init():
    a = Amount('1 GOLOS')
    assert dict(a) == {'amount': 1.0, 'asset': 'GOLOS'}
예제 #25
0
 def sp(self):
     vests = Amount(self["vesting_shares"]).amount
     return round(self.converter.vests_to_sp(vests), 3)
예제 #26
0
def main():

    parser = argparse.ArgumentParser(
        description='Use this script to estimate potential upvote profit',
        epilog='Report bugs to: https://github.com/bitfag/golos-scripts/issues'
    )
    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='enable debug output'),
    parser.add_argument('-c',
                        '--config',
                        default='./common.yml',
                        help='specify custom path for config file')
    parser.add_argument(
        'account', help='specify account which upvote should be estimated')
    parser.add_argument('-p',
                        '--percent',
                        default=100,
                        type=float,
                        help='specify upvote percent')
    parser.add_argument('--curve',
                        default='linear',
                        choices=['quadratic', 'linear'],
                        help='select curve type')
    parser.add_argument('-u',
                        '--url',
                        help='post id in format @author/article or full url')
    args = parser.parse_args()

    # create logger
    if args.debug == True:
        log.setLevel(logging.DEBUG)
    else:
        log.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    formatter = logging.Formatter("%(levelname)s: %(message)s")
    handler.setFormatter(formatter)
    log.addHandler(handler)

    # parse config
    with open(args.config, 'r') as ymlfile:
        conf = yaml.load(ymlfile)

    golos = Steem(nodes=conf['nodes_old'], keys=conf['keys'])

    if args.curve == 'quadratic':
        if not args.url:
            log.critical(
                'you need to provide --url when using quadratic curve')
            sys.exit(1)
        # extract author and post permlink from args.url
        p = re.search('@(.*?)/([^/]+)', args.url)
        if p == None:
            log.critical('Wrong post id specified')
            sys.exit(1)
        else:
            author = p.group(1)
            log.debug('author: {}'.format(author))

            post_permlink = p.group(2)
            log.debug('permlink: {}'.format(post_permlink))

        post = functions.get_post_content(golos, author, post_permlink)
        if not post:
            log.critical('could not find post in blockchain')
            sys.exit(1)

        # current post rshares
        net_rshares = int(post['net_rshares'])

        # current pending_payout_value, GBG
        current_pending_payout_value = post['pending_payout_value']
        log.info('current pending_payout_value: {}'.format(
            current_pending_payout_value))

        # estimate current expected author reward
        author_payout_gp, author_payout_gbg, author_payout_golos = functions.estimate_author_payout(
            golos, current_pending_payout_value)
        log.info(
            'estimated author payout: {:.3f} GBG, {:.3f} GOLOS, {:.3f} GP'.
            format(author_payout_gbg, author_payout_golos, author_payout_gp))

        rshares = functions.calc_rshares(golos, args.account, args.percent)
        new_rshares = net_rshares + rshares

        new_payout = functions.calc_payout(golos, new_rshares)
        new_payout_gbg = functions.convert_golos_to_gbg(golos,
                                                        new_payout,
                                                        price_source='median')
        new_payout_gbg = Amount('{} GBG'.format(new_payout_gbg))
        log.info('new pending_payout_value: {}'.format(new_payout_gbg))

        payout_diff = new_payout_gbg.amount - current_pending_payout_value.amount
        log.info('pending_payout diff: {:.3f}'.format(payout_diff))

        # estimate new author reward
        author_payout_gp, author_payout_gbg, author_payout_golos = functions.estimate_author_payout(
            golos, new_payout_gbg)
        log.info(
            'new estimated author payout: {:.3f} GBG, {:.3f} GOLOS, {:.3f} GP'.
            format(author_payout_gbg, author_payout_golos, author_payout_gp))

    elif args.curve == 'linear':

        rshares = functions.calc_rshares(golos, args.account, args.percent)
        payout = functions.calc_payout(golos, rshares)
        payout_gbg = functions.convert_golos_to_gbg(golos,
                                                    payout,
                                                    price_source='median')
        payout_gbg = Amount('{} GBG'.format(payout_gbg))
        log.info('raw upvote value: {} or {:.3f} GOLOS'.format(
            payout_gbg, payout))
        author_payout_gp, author_payout_gbg, author_payout_golos = functions.estimate_author_payout(
            golos, payout_gbg)
        log.info(
            'estimated author payout: {:.3f} GBG, {:.3f} GOLOS, {:.3f} GP'.
            format(author_payout_gbg, author_payout_golos, author_payout_gp))

        author_payout_gbg_repr = author_payout_gbg
        author_payout_gbg_repr += functions.convert_golos_to_gbg(
            golos, author_payout_golos, price_source='market')
        author_payout_gbg_repr += functions.convert_golos_to_gbg(
            golos, author_payout_gp, price_source='market')
        log.info(
            'estimated author payout in GBG representation: {:.3f} GBG'.format(
                author_payout_gbg_repr))
예제 #27
0
def get_bandwidth(steemd_instance, account, type='market'):
    """ Estimate current account bandwidth and usage ratio
        :param Steem steemd_instance: Steem() instance to use when accesing a RPC
        :param str account: account name
        :param str type: 'market' used for transfer operations, forum - for posting and voting
    """

    a = Account(account, steemd_instance=steemd_instance)

    global_props = steemd_instance.get_dynamic_global_properties()

    account_vshares = Amount(a['vesting_shares']).amount
    log.debug('{:.<30}{:.>30.0f}'.format('account_vshares:', account_vshares))

    # get bandwidth info from network
    if type == 'market':
        account_average_bandwidth = int(a['average_market_bandwidth'])
        last_bw_update_time = datetime.strptime(
            a['last_market_bandwidth_update'], '%Y-%m-%dT%H:%M:%S')
    elif type == 'forum':
        account_average_bandwidth = int(a['average_bandwidth'])
        last_bw_update_time = datetime.strptime(a['last_bandwidth_update'],
                                                '%Y-%m-%dT%H:%M:%S')

    # seconds passed since last bandwidth update
    elapsed_time = (datetime.utcnow() - last_bw_update_time).total_seconds()

    max_virtual_bandwidth = int(global_props['max_virtual_bandwidth'])
    log.debug('{:.<30}{:.>30.0f}'.format('max_virtual_bandwidth:',
                                         max_virtual_bandwidth))
    log.debug('{:.<30}{:.>30.0f}'.format(
        'max_virtual_bandwidth, KB:',
        max_virtual_bandwidth / STEEMIT_BANDWIDTH_PRECISION / 1024))

    total_vesting_shares = Amount(global_props['total_vesting_shares']).amount
    log.debug('{:.<30}{:.>30.0f}'.format('total_vesting_shares:',
                                         total_vesting_shares))

    # calculate bandwidth regeneration
    if elapsed_time > STEEMIT_BANDWIDTH_AVERAGE_WINDOW_SECONDS:
        new_bandwidth = 0
    else:
        new_bandwidth = (
            ((STEEMIT_BANDWIDTH_AVERAGE_WINDOW_SECONDS - elapsed_time) *
             account_average_bandwidth) /
            STEEMIT_BANDWIDTH_AVERAGE_WINDOW_SECONDS)

    # example code to estimate whether your new transaction will exceed bandwidth or not
    #trx_size = 1024*2 # imagine 2 KB trx
    #trx_bandwidth = trx_size * STEEMIT_BANDWIDTH_PRECISION
    #account_average_bandwidth = new_bandwidth + trx_bandwidth

    account_average_bandwidth = new_bandwidth
    log.debug('{:.<30}{:.>30.0f}'.format('account_average_bandwidth:',
                                         account_average_bandwidth))

    # c++ code:
    # has_bandwidth = (account_vshares * max_virtual_bandwidth) > (account_average_bandwidth * total_vshares);

    avail = account_vshares * max_virtual_bandwidth
    used = account_average_bandwidth * total_vesting_shares
    log.debug('{:.<30}{:.>30.0f}'.format('used:', used))
    log.debug('{:.<30}{:.>30.0f}'.format('avail:', avail))

    used_ratio = used / avail
    log.info('{:.<30}{:.>30.2%}'.format('used ratio:', used_ratio))

    # account bandwidth is actually a representation of sent bytes, so get these bytes
    used_kb = account_average_bandwidth / STEEMIT_BANDWIDTH_PRECISION / 1024
    # market ops uses x10 bandwidth
    if type == 'market':
        used_kb = used_kb / 10
    log.info('{:.<30}{:.>30.2f}'.format('used KB:', used_kb))

    # available account bandwidth is a fraction of max_virtual_bandwidth based on his portion of total_vesting_shares
    avail_kb = account_vshares / total_vesting_shares * max_virtual_bandwidth / STEEMIT_BANDWIDTH_PRECISION / 1024
    if type == 'market':
        avail_kb = avail_kb / 10
    log.info('{:.<30}{:.>30.2f}'.format('avail KB:', avail_kb))

    if used < avail:
        log.debug('has bandwidth')
    else:
        log.debug('no bandwidth')

    return used / avail * 100
예제 #28
0
def main():

    parser = argparse.ArgumentParser(
        description=
        'Scan account history looking for author or curator payouts',
        epilog='Report bugs to: https://github.com/bitfag/golos-scripts/issues'
    )
    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='enable debug output'),
    parser.add_argument('-c',
                        '--config',
                        default='./common.yml',
                        help='specify custom path for config file')
    parser.add_argument(
        '-t',
        '--type',
        default='author',
        choices=['author', 'curator'],
        help='reward type, "author" or "curator", default: author')
    parser.add_argument('account', help='account to scan')
    args = parser.parse_args()

    # create logger
    if args.debug == True:
        log.setLevel(logging.DEBUG)
    else:
        log.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s")
    handler.setFormatter(formatter)
    log.addHandler(handler)

    # parse config
    with open(args.config, 'r') as ymlfile:
        conf = yaml.load(ymlfile)

    if args.type == 'author':
        ops = ['author_reward']
    elif args.type == 'curator':
        ops = ['curation_reward']

    golos = Steem(nodes=conf['nodes_old'], keys=conf['keys'])
    cv = Converter(golos)

    account = Account(args.account, steemd_instance=golos)
    history = account.rawhistory(only_ops=ops)

    for item in history:
        #pprint(item)

        permlink = item[1]['op'][1]['permlink']
        payout_timestamp = datetime.strptime(item[1]['timestamp'],
                                             '%Y-%m-%dT%H:%M:%S')

        sbd_payout = Amount(item[1]['op'][1]['sbd_payout'])
        steem_payout = Amount(item[1]['op'][1]['steem_payout'])
        vesting_payout = Amount(item[1]['op'][1]['vesting_payout'])
        gp = cv.vests_to_sp(vesting_payout.amount)

        golos_payout = steem_payout.amount + gp
        gpg_repr = sbd_payout.amount + functions.convert_golos_to_gbg(
            golos, golos_payout, price_source='market')

        print('{} {}: {} {} {:.3f} GP, GBG repr: {:.3f}'.format(
            payout_timestamp, permlink, sbd_payout, steem_payout, gp,
            gpg_repr))
def main():

    parser = argparse.ArgumentParser(
        description='Find all vesting withdrawals with rates and dates',
        epilog='Report bugs to: https://github.com/bitfag/golos-scripts/issues'
    )
    parser.add_argument('-d',
                        '--debug',
                        action='store_true',
                        help='enable debug output'),
    parser.add_argument('-c',
                        '--config',
                        default='./common.yml',
                        help='specify custom path for config file')
    parser.add_argument(
        '-m',
        '--min-mgests',
        default=100,
        type=float,
        help=
        'look for account with vesting shares not less than X MGESTS, default is 100'
    )
    args = parser.parse_args()

    # create logger
    if args.debug == True:
        log.setLevel(logging.DEBUG)
    else:
        log.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    formatter = logging.Formatter("%(asctime)s %(levelname)s: %(message)s")
    handler.setFormatter(formatter)
    log.addHandler(handler)

    # parse config
    with open(args.config, 'r') as ymlfile:
        conf = yaml.load(ymlfile)

    golos = Steem(nodes=conf['nodes_old'], keys=conf['keys'])

    c = golos.get_account_count()
    log.debug('total accounts: {}'.format(c))

    accs = golos.get_all_usernames()

    start = datetime.utcnow()

    # get all accounts in one batch
    all_accounts = golos.get_accounts(accs)

    # we well get summary info about total withdrawal rate and number of accounts
    sum_rate = float()
    count = int()

    cv = Converter(golos)
    steem_per_mvests = cv.steem_per_mvests()

    for a in all_accounts:
        vshares = Amount(a['vesting_shares'])
        mgests = vshares.amount / 1000000
        rate = Amount(a['vesting_withdraw_rate'])
        d = datetime.strptime(a['next_vesting_withdrawal'],
                              '%Y-%m-%dT%H:%M:%S')

        if mgests > args.min_mgests and rate.amount > 1000:
            # We use own calculation instead of cv.vests_to_sp() to speed up execution
            # avoiding API call on each interation
            rate_gp = rate.amount / 1e6 * steem_per_mvests
            gp = vshares.amount / 1e6 * steem_per_mvests
            sum_rate += rate_gp
            count += 1

            print('{:<16} {:<18} {:>6.0f} {:>8.0f}'.format(
                a['name'], d.strftime('%Y-%m-%d %H:%M'), rate_gp, gp))


# non-pretty format
#            log.info('{} {} {:.0f} / {:.0f}'.format(
#                                       a['name'],
#                                       d.strftime('%Y-%m-%d %H:%M'),
#                                       rate_gp, gp))

    log.debug('accounts iteration took {:.2f} seconds'.format(
        (datetime.utcnow() - start).total_seconds()))

    log.info(
        'numbers of matching accounts on vesting withdrawal: {}'.format(count))
    log.info('sum rate: {:.0f}'.format(sum_rate))
예제 #30
0
async def calc_debt(ctx, usd):

    price_usd_gold, price_btc_usd, (price_btc_golos, _) = await asyncio.gather(
        get_price_usd_gold_cbr(), get_price_btc_usd_exchanges(),
        get_bitshares_center_price(ctx))
    print('External price USD/XAU: {:.5f}'.format(price_usd_gold))
    print('External price USD/BTC: {:.8f}'.format(price_btc_usd))
    print('External price BTC/GOLOS: {:.8f}'.format(price_btc_golos))

    # BTC/GOLD
    price_btc_gold = price_usd_gold / price_btc_usd
    print('External price BTC/XAU: {:.8f}'.format(price_btc_gold))

    props = ctx.helper.get_dynamic_global_properties()
    sbd_supply = Amount(props['current_sbd_supply'])
    current_supply = Amount(props['current_supply'])
    virtual_supply = Amount(props['virtual_supply'])
    total_reward_fund_steem = Amount(props['total_reward_fund_steem'])

    median = ctx.helper.converter.sbd_median_price()
    median_estimated = ctx.helper.estimate_median_price()

    # libraries/chain/database.cpp
    # this min_price caps system debt to 10% of GOLOS market capitalisation
    min_price = 9 * sbd_supply.amount / current_supply.amount
    print('Minimal possible median price GBG/GOLOS: {:.3f}'.format(min_price))

    # #define STEEMIT_100_PERCENT 10000
    # this is current GBG percent printed
    percent_sbd = sbd_supply.amount / median * 100 / virtual_supply.amount
    print('System GBG debt percent (by blockchain median): {:.2f}'.format(
        percent_sbd))
    percent_sbd = sbd_supply.amount / median_estimated * 100 / virtual_supply.amount
    print(
        'System GBG debt percent (by feed price): {:.2f}'.format(percent_sbd))

    if percent_sbd > 10:
        # estimate supply when debt will return to 10% at current price
        target_supply = 9 * sbd_supply.amount / median_estimated
        print('GBG supply: {:,.0f} GBG'.format(sbd_supply.amount))
        print('Current supply: {:,.0f} GOLOS'.format(current_supply.amount))
        print('Expected supply for reaching 10% debt: {:,.0f} GOLOS'.format(
            target_supply))

        converted_supply = sbd_supply.amount / median
        print(
            'New GOLOS amount on full convertation by blockchain price: {:,.0f} GOLOS'
            .format(converted_supply))

        converted_supply = sbd_supply.amount / median_estimated
        print(
            'New GOLOS amount on full convertation by feed price: {:,.0f} GOLOS'
            .format(converted_supply))
        print(
            'Total supply after full convertation by feed price: {:,.0f} GOLOS'
            .format(current_supply.amount + converted_supply))

        # model gradual conversion of all GBG supply
        step = 10000
        price = min_price
        gbg = sbd_supply.amount
        golos = current_supply.amount
        flag = False

        while gbg > step:
            gbg -= step
            golos += step / price
            price = max(9 * gbg / golos, median_estimated)
            virtual_supply = golos + gbg / price
            percent_sbd = gbg / median_estimated * 100 / virtual_supply
            if percent_sbd < 20 and not flag:
                print('GBG supply at 20% debt: {:,.0f}'.format(gbg))
                print('New GOLOS amount from conversion to 20% debt: {:,.0f}'.
                      format(golos - current_supply.amount))
                flag = True
        new_supply = golos - current_supply.amount
        print(
            'New GOLOS amount after gradual convertation of all GBG with step {}: {:,.0f} GOLOS'
            .format(step, new_supply))

    sbd_print_rate = props['sbd_print_rate'] / 100
    gbg_emission_week = (total_reward_fund_steem.amount /
                         2) * median * sbd_print_rate / 100
    gbg_emission_day = gbg_emission_week / 7
    print('GBG print rate: {:.2f}'.format(sbd_print_rate))
    print('Approximate GBG emission per day: {:.0f}'.format(gbg_emission_day))

    print('Conversion-derived price BTC/GBG: {:.8f}'.format(price_btc_golos /
                                                            median))

    if usd:
        print('Approximate USD/GOLOS price at 2%-debt point: {:.3f}'.format(
            price_usd_gold * min_price * 5))
        print('Approximate USD/GOLOS price at 5%-debt point: {:.3f}'.format(
            price_usd_gold * min_price * 2))
        print('Approximate USD/GOLOS price at 10%-debt point: {:.3f}'.format(
            price_usd_gold * min_price))
    else:
        print('Approximate BTC/GOLOS price at 2%-debt point: {:.8f}'.format(
            price_btc_gold * min_price * 5))
        print('Approximate BTC/GOLOS price at 5%-debt point: {:.8f}'.format(
            price_btc_gold * min_price * 2))
        print('Approximate BTC/GOLOS price at 10%-debt point: {:.8f}'.format(
            price_btc_gold * min_price))