예제 #1
0
def get_delegate_payouts(account, steem, current_datetime, min_days,
                         investor_share):
    """ Returns pending payouts for investors

    Parameters
    ----------
    account: str
    steem: Steem
    current_datetime: datetime
    min_days: int
        minimum days of delegation before payout
    investor_share: float

    Returns
    -------
    dict of float:
        SBD to pay to each investor
    dict of float:
        STEEM to pay to each investor

    """
    assert 0 < investor_share <= 1

    current_datetime = pd.to_datetime(current_datetime)
    threshold_date = current_datetime - pd.Timedelta(days=min_days)

    vests_by = none_error_retry(get_delegates_and_shares,
                                retries=3,
                                errors=(TypeError, ))(account, steem)
    filtered_vests_by = {
        delegator: dict_['vests']
        for delegator, dict_ in vests_by.items()
        if dict_['timestamp'] < threshold_date
    }
    acc = none_error_retry(Account, errors=(Exception, ))(account, steem)

    pending_sbd = acc.balances['rewards']['SBD']
    pending_steem = acc.balances['rewards']['STEEM']
    vests = acc.balances['total']['VESTS']
    filtered_vests_by[account] = vests

    total_vests = sum(filtered_vests_by.values())
    sbd_payouts = {
        delegator: np.round(vests / total_vests * investor_share * pending_sbd,
                            decimals=3)
        for delegator, vests in filtered_vests_by.items()
        if delegator != account
    }

    steem_payouts = {
        delegator:
        np.round(vests / total_vests * investor_share * pending_steem,
                 decimals=3)
        for delegator, vests in filtered_vests_by.items()
        if delegator != account
    }

    return sbd_payouts, steem_payouts
예제 #2
0
def check_all_ops_in_block(block_num, steem, account):
    """ Gets all posts from one block

    Parameters
    ----------
    block_num: int
    steem: Steem
    account str

    Returns
    -------
    List of tuples with comment authors and permalinks

    """
    try:
        operations = none_error_retry(steem.get_ops_in_block)(block_num, False)
        if operations:
            return extract_comment_authors_and_permalinks(operations, account)
        else:
            logger.warning(
                'Could not find any operations for block {}'.format(block_num))
        return []
    except Exception as e:
        logger.exception(
            'Error for block {}. Reconnecting...'.format(block_num))
        steem.reconnect()
    return []
예제 #3
0
def get_all_posts_from_block(block_num, steem,
                             exclude_authors_and_permalinks=None):
    """ Gets all posts from one block

    Parameters
    ----------
    block_num: int
    steem: MPSteem
    exclude_authors_and_permalinks: set of tuples of strings
        Exclude these authors and permalinks to get less duplicates

    Returns
    -------
    List of post dicts and set of authors and permalinks

    """
    try:
        operations = none_error_retry(steem.get_ops_in_block)(block_num, False)
        if operations:
            authors_and_permalinks = extract_authors_and_permalinks(operations)
            if exclude_authors_and_permalinks:
                authors_and_permalinks -= exclude_authors_and_permalinks
            if authors_and_permalinks:
                return get_post_data(authors_and_permalinks, steem), authors_and_permalinks
            else:
                logger.debug('Could not find any posts for block {}'.format(block_num))
        else:
            logger.warning('Could not find any operations for block {}'.format(block_num))
    except Exception as e:
        logger.exception('Error for block {}. Reconnecting...'.format(block_num))
        steem.reconnect()
    return [], set()
예제 #4
0
def _get_upvote_payments_parrallel(accounts, steem, min_datetime,
                                   max_datetime):
    results = {}
    for account in accounts:
        result = none_error_retry(get_upvote_payments,
                                  errors=(Exception, ),
                                  retries=5,
                                  sleep_time=2)(account, steem, min_datetime,
                                                max_datetime)
        results = extend_upvotes_and_payments(results, result)

    return result
예제 #5
0
def history_reverse(account,
                    steem,
                    start_index,
                    filter_by=None,
                    batch_size=1000,
                    raw_output=False):
    """ Stream account history in reverse chronological order."""
    acc = none_error_retry(Account, errors=(Exception, ))(account, steem)
    i = start_index
    if batch_size > start_index:
        batch_size = start_index
    while i > 0:
        if i - batch_size < 0:
            batch_size = i
        yield from none_error_retry(acc.get_account_history,
                                    errors=(Exception, ))(
                                        index=i,
                                        limit=batch_size,
                                        order=-1,
                                        filter_by=filter_by,
                                        raw_output=raw_output,
                                    )
        i -= (batch_size + 1)
예제 #6
0
def get_delegates_and_shares(account, steem):
    """ Queries all delegators to `account` and the amount of shares

    Parameters
    ----------
    account: str
    steem: Steem

    Returns
    -------
    dict of float

    """
    acc = none_error_retry(Account, errors=(Exception, ))(account, steem)
    delegators = {}
    for tr in none_error_retry(
            acc.history_reverse,
            errors=(Exception, ))(filter_by='delegate_vesting_shares'):
        try:
            delegator = tr['delegator']
            if delegator not in delegators:
                shares = tr['vesting_shares']
                if shares.endswith(' VESTS'):
                    shares = float(shares[:-6])
                    timestamp = pd.to_datetime(tr['timestamp'])
                    delegators[delegator] = {
                        'vests': shares,
                        'timestamp': timestamp
                    }
                else:
                    raise RuntimeError('Weird shares {}'.format(shares))

        except Exception as e:
            logger.exception('Error extracting delegator from '
                             '{}, restarting steem'.format(tr))
            steem.reconnect()
    return delegators
예제 #7
0
def get_block_headers_between_offset_start(start_datetime, end_datetime,
                                           end_offset_num, steem):
    """ Returns block headers between a date range

    NOT used in production!

    Parameters
    ----------
    start_datetime: datetime
    end_datetime: datetime
    end_offset_num: offset from wich to seach backwards
    steem: Steem object

    Returns
    -------
    Ordereddict: block_num -> header

    """
    start_datetime = pd.to_datetime(start_datetime)
    end_datetime = pd.to_datetime(end_datetime)
    current_block_num = end_offset_num
    headers = OrderedDict()
    logger.info('Collecting header infos')
    while True:
        try:
            header = none_error_retry(steem.get_block_header)(current_block_num)
            current_datetime = pd.to_datetime(header['timestamp'])
            if start_datetime <= current_datetime and current_datetime <= end_datetime:
                header['timestamp'] = current_datetime
                headers[current_block_num] = header
            if current_datetime < start_datetime:
                break
        except Exception:
            logger.exception('Error for block num {}. Reconnecting...'.format(current_block_num))
            steem.reconnect()
        current_block_num -= 1
        if current_block_num % 100 == 99:
            logger.debug('Bin alread {} headers'.format(len(headers)))
    return headers
예제 #8
0
def find_nearest_index(target_datetime,
                       account,
                       steem,
                       latest_index=None,
                       max_tries=5000,
                       index_tolerance=2):
    """ Finds nearest account action index to `target_datetime`

    Parameters
    ----------
    target_datetime: datetime
    steem: Steem object
    latest_index: int
        latest index number in acount index
        leave None to get from steem directly
    max_tries: int
        number of maximum tries
    index_tolerance: int
        tolerance too closest index number

    Returns
    -------
    int: best matching index
    datetime: datetime of matching index

    """
    acc = none_error_retry(Account, errors=(Exception, ))(account, steem)

    if latest_index is None:
        latest_index = none_error_retry(next, errors=(Exception, ))(
            none_error_retry(acc.history_reverse,
                             errors=(Exception, ))(batch_size=1))['index']

    current_index = latest_index
    best_largest_index = latest_index

    action = none_error_retry(next, errors=(Exception, ))(none_error_retry(
        acc.get_account_history, errors=(Exception, ))(best_largest_index,
                                                       limit=1))
    best_largest_datetime = pd.to_datetime(action['timestamp'])
    if target_datetime > best_largest_datetime:
        logger.debug('Target beyond largest block num')
        return latest_index, best_largest_datetime

    best_smallest_index = 1
    increase = index_tolerance + 1
    current_datetime = None
    for _ in range(max_tries):
        try:
            action = none_error_retry(next, errors=(Exception, ))(
                none_error_retry(acc.get_account_history,
                                 errors=(Exception, ))(current_index, limit=1))
            current_datetime = pd.to_datetime(action['timestamp'])
            if increase <= index_tolerance:
                return current_index, current_datetime
            else:

                if current_datetime < target_datetime:
                    best_smallest_index = current_index
                else:
                    best_largest_index = current_index

                increase = (best_largest_index - best_smallest_index) // 2
                current_index = best_smallest_index + increase

                if current_index < 0 or current_index > latest_index:
                    raise RuntimeError('Seriously? Error for '
                                       'account {}: current_index {} '
                                       'latest_index {}'.format(
                                           account, current_index,
                                           latest_index))
        except StopIteration:
            logger.exception('Problems for index {} of account {}. '
                             'Reraising...'.format(current_index, account))
            raise
        except Exception:
            logger.exception('Problems for index {} of account {}. '
                             'Reconnecting...'.format(current_index, account))
            current_index -= 1
            best_largest_index -= 1
            steem.reconnect()
            acc = none_error_retry(Account, errors=(Exception, ))(account,
                                                                  steem)
            if current_index <= 1:
                logger.error('Could not find index, raising StopIteration')
                raise StopIteration('Problems for account {}'.format(account))
예제 #9
0
def test_none_error_retry():
    result = none_error_retry(g, sleep_time=0.1)()
    assert result is None
예제 #10
0
def find_nearest_block_num(target_datetime, steem,
                           latest_block_num=None,
                           max_tries=5000,
                           block_num_tolerance=0):
    """ Finds nearest block number to `target_datetime`

    Parameters
    ----------
    target_datetime: datetime
    steem: Steem object
    latest_block_num: int
        latest block number in bchain
        leave None to get from steem directly
    max_tries: int
        number of maximum tries
    block_num_tolerance: int
        tolerance too closest in block

    Returns
    -------
    int: best matching block number
    datetime: datetime of matching block

    """
    if latest_block_num is None:
        latest_block_num = none_error_retry(Blockchain(steem).get_current_block_num)()

    current_block_num = latest_block_num
    best_largest_block_num = latest_block_num

    header = none_error_retry(steem.get_block_header)(best_largest_block_num)
    best_largest_datetime = pd.to_datetime(header['timestamp'])
    if target_datetime > best_largest_datetime:
        logger.warning('Target beyond largest block num')
        return latest_block_num, best_largest_datetime

    best_smallest_block_num = 1
    increase = block_num_tolerance + 1
    current_datetime = None
    for _ in range(max_tries):
        try:
            header = none_error_retry(steem.get_block_header)(current_block_num)
            current_datetime = pd.to_datetime(header['timestamp'])
            if increase <= block_num_tolerance:
                return current_block_num, current_datetime
            else:

                if current_datetime < target_datetime:
                    best_smallest_block_num = current_block_num
                else:
                    best_largest_block_num = current_block_num

                increase = (best_largest_block_num - best_smallest_block_num) // 2
                current_block_num = best_smallest_block_num + increase

                if current_block_num < 0 or current_block_num > latest_block_num:
                    raise RuntimeError('Seriously?')
        except Exception:
            logger.exception('Problems for block num {}. Reconnecting...'
                             ''.format(current_block_num))
            current_block_num -= 1
            best_smallest_block_num -= 1
            steem.reconnect()
            if current_block_num <= 1:
                logger.error('Could not find block num returning 1')
                return 1, current_datetime