async def cmd_status(command_str, discord_message, apis):
    # TODO: this function should build a list of label, status tuples then
    # format them all at the end
    response = "```diff\n"
    # TODO: sort exchange list alphabetically
    for exchange in apis.exchanges.all_exchanges:
        full_exchange_name = "{} [{}]:".format(exchange.exchange_name,
                                                    exchange.currency_symbol)
        if exchange.update_failure_count > 0:
            if exchange.last_updated_time == 0:
                time_str = "not yet updated" 
            else:
                time_str = "last updated {} ago".format(seconds_to_time(time.time() - exchange.last_updated_time),
                                                        granularity=1)
            response += "- {:<24} {}\n".format(full_exchange_name,
                                               time_str)
        else:
            response += "+ {:<24} OK\n".format(full_exchange_name)

    ping_times = await get_ping_times(command_str, discord_message, apis)
    for url, latency in ping_times:
        url = url + ':'
        if latency == None:
            response += "- {:<24} down\n".format(url)
        else:
            response += "+ {:<24} {:.1f} ms\n".format(url, latency)
    try:
        response += "+ {:<24} {:.2f} MB\n".format("Memory:", rss_resource())
    except ModuleNotFoundError:
        pass

    return response + "```"
async def cmd_blocktime(command_str, discord_message, apis):
    if apis.token.seconds_per_reward == None:
        return ":shrug:"

    fmt_str = "Current average block time: **{}** (average taken over the last {})"
    result = fmt_str.format('unknown' if apis.token.seconds_per_reward == float('inf') else seconds_to_time(apis.token.seconds_per_reward),
                            seconds_to_time(apis.token.seconds_since_readjustment, granularity=1))
    return result
async def cmd_hashrate(command_str, discord_message, apis):
    if apis.token.estimated_hashrate_since_readjustment == None:
        return ":shrug:"

    fmt_str = "Estimated hashrate: **{}** over the last {}, and **{}** over the last 24 hours."
    result = fmt_str.format(to_readable_thousands(apis.token.estimated_hashrate_since_readjustment, unit_type="hashrate", decimals=2),
                            seconds_to_time(apis.token.seconds_since_readjustment, granularity=2),
                            to_readable_thousands(apis.token.estimated_hashrate_24h, unit_type="hashrate", decimals=2))
    return result
async def cmd_hashrate(command_str, discord_message, apis):
    if apis.token.estimated_hashrate_since_readjustment is None:
        result = ":shrug:"
    # check if the 24h hashrate estimate was not calculated
    #
    # unfortunately infura v3 removed the functions necessary to calculate it, and
    # we store 'None' in that case. If they ever being back support it should be
    # populated again and just work
    elif apis.token.estimated_hashrate_24h is None:
        fmt_str = "Estimated hashrate: **{}** over the last {}."
        result = fmt_str.format(to_readable_thousands(apis.token.estimated_hashrate_since_readjustment, unit_type="hashrate", decimals=2),
                                seconds_to_time(apis.token.seconds_since_readjustment, granularity=2))
    else:
        fmt_str = "Estimated hashrate: **{}** over the last {}, and **{}** over the last 24 hours."
        result = fmt_str.format(to_readable_thousands(apis.token.estimated_hashrate_since_readjustment, unit_type="hashrate", decimals=2),
                                seconds_to_time(apis.token.seconds_since_readjustment, granularity=2),
                                to_readable_thousands(apis.token.estimated_hashrate_24h, unit_type="hashrate", decimals=2))
    return result
async def cmd_difficulty(command_str, discord_message, apis):
    if apis.token.difficulty == None:
        return ":shrug:"

    if apis.token.seconds_until_readjustment == float('inf'):
        retarget_str = ''
    else:
        retarget_str = " ({} until next retarget)".format(seconds_to_time(apis.token.seconds_until_readjustment))

    fmt_str = "Current difficulty: **{}** {}"
    result = fmt_str.format(to_readable_thousands(apis.token.difficulty, unit_type='long'),
                            retarget_str)
    return result
async def cmd_income(command_str, discord_message, apis):
    if apis.token.difficulty is None:
        return "not sure yet... waiting on my APIs :sob:"

    try:
        command, hashrate = command_str.split(maxsplit=1)
    except:
        return "Bad hashrate; try `!income 5`, `!income 300mh`, or `!income 2.8gh`"

    multipliers = (
        ('k', 1e3),
        ('m', 1e6),
        ('g', 1e9),
        ('t', 1e12),
        ('p', 1e15),
        ('e', 1e18),
        ('z', 1e21),
        ('y', 1e24))
    selected_multiplier = 1e9
    for char, mult in multipliers:
        if char in hashrate:
            selected_multiplier = mult

    match = re.match("([<\d.,]+)", hashrate)
    if not match:
        return "Bad hashrate; try `!income 5`, `!income 300mh`, or `!income 2.8gh`"
    try:
        hashrate = string_to_float(match.group(1)) * selected_multiplier
    except ValueError:
        return "Bad hashrate; try `!income 5`, `!income 300mh`, or `!income 2.8gh`"

    if hashrate == 0:
        return "Bad hashrate; try `!income 5`, `!income 300mh`, or `!income 2.8gh`"

    tokens_per_day = 0.8 * 86400 * apis.token.reward * hashrate / ((2**22) * apis.token.difficulty)
    seconds_per_block = 1.2 * ((2**22) * apis.token.difficulty) / hashrate

    if tokens_per_day > 1:
        tokens_over_time_str = "**{}** tokens/day".format(prettify_decimals(tokens_per_day))
    else:
        tokens_over_time_str = "**{}** tokens/week".format(prettify_decimals(tokens_per_day*7))

    fmt_str = "Income for {}: {}; **{}** per block solo"
    return fmt_str.format(to_readable_thousands(hashrate, unit_type='hashrate'),
                          tokens_over_time_str,
                          seconds_to_time(seconds_per_block))
async def cmd_era(command_str, discord_message, apis):
    try:
        apis.token.era
    except AttributeError:
        return ":shrug:"

    if apis.token.era == None:
        return ":shrug:"

    if apis.token.era == 39:
        return "In era 39 / 39"

    fmt_str = "Current era: **{}** / 39.  In {} the reward will drop to **{}** {}"
    result = fmt_str.format(apis.token.era,
                            seconds_to_time(apis.token.seconds_remaining_in_era),
                            apis.token.reward / 2,
                            apis.token.symbol)
    return result
async def cmd_uptime(command_str, discord_message, apis):
    return "Uptime: {}".format(seconds_to_time(time.time() - apis.start_time))
Example #9
0
    def test_seconds_to_time(self):
        from formatting_helpers import seconds_to_time

        self.assertEqual(seconds_to_time(3600), '1 hour')
        self.assertEqual(seconds_to_time(100), '1 minute, 40 seconds')
        self.assertEqual(seconds_to_time(0.1), '0 seconds')
        self.assertEqual(seconds_to_time(0), '0 seconds')
        self.assertEqual(seconds_to_time(0, show_subsecond_values=True),
                         '0 seconds')
        self.assertEqual(
            seconds_to_time(0, granularity=5, show_subsecond_values=True),
            '0 seconds')

        self.assertEqual(seconds_to_time(3661, granularity=1), '1 hour')
        self.assertEqual(seconds_to_time(3661, granularity=2),
                         '1 hour, 1 minute')
        self.assertEqual(seconds_to_time(3661, granularity=3),
                         '1 hour, 1 minute, 1 second')

        self.assertEqual(seconds_to_time(0.1, show_subsecond_values=True),
                         '100 milliseconds')
        self.assertEqual(
            seconds_to_time(0.12301, granularity=1,
                            show_subsecond_values=True), '123 milliseconds')
        self.assertEqual(
            seconds_to_time(0.12391, granularity=1,
                            show_subsecond_values=True), '123 milliseconds')
        # python float error causes this one to be off by 1, but thats OK
        self.assertEqual(seconds_to_time(0.12301, show_subsecond_values=True),
                         '123 milliseconds, 9 nanoseconds')
        self.assertEqual(seconds_to_time(0.12391, show_subsecond_values=True),
                         '123 milliseconds, 910 nanoseconds')