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))
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')