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
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 []
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()
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
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)
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
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
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))
def test_none_error_retry(): result = none_error_retry(g, sleep_time=0.1)() assert result is None
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