From d8599e5f67b87887046d6856369b8ac3b124bb26 Mon Sep 17 00:00:00 2001 From: Michael Schmoock Date: Wed, 15 May 2019 09:29:08 +0200 Subject: [PATCH] pylightning: adds msat.to_approx_str() method Tries to return the approxmost posible string of a Millisatoshi amount using various unit representations. The function will round to an effective number of digits. Default: 3. ``` >>> Millisatoshi("100000sat").to_approx_str() '0.001btc' >>> Millisatoshi("100msat").to_approx_str() '0.1sat' >>> Millisatoshi("10000000sat").to_approx_str() '0.1btc' ``` --- contrib/pylightning/lightning/lightning.py | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/contrib/pylightning/lightning/lightning.py b/contrib/pylightning/lightning/lightning.py index 8152d1b22..77e63c682 100644 --- a/contrib/pylightning/lightning/lightning.py +++ b/contrib/pylightning/lightning/lightning.py @@ -1,6 +1,7 @@ from decimal import Decimal import json import logging +from math import floor, log10 import socket __version__ = "0.0.7.1" @@ -85,6 +86,37 @@ class Millisatoshi: else: return '{:.8f}btc'.format(self.to_btc()) + def to_approx_str(self, digits: int = 3): + """Returns the shortmost string using common units representation. + + Rounds to significant `digits`. Default: 3 + """ + round_to_n = lambda x, n: round(x, -int(floor(log10(x))) + (n - 1)) + result = None + + # we try to increase digits to check if we did loose out on precision + # without gaining a shorter string, since this is a rarely used UI + # function, performance is not an issue. Adds at least one iteration. + while True: + # first round everything down to effective digits + amount_rounded = round_to_n(self.millisatoshis, digits) + # try different units and take shortest resulting normalized string + amounts_str = [ + "%gbtc" % (amount_rounded / 1000 / 10**8), + "%gsat" % (amount_rounded / 1000), + "%gmsat" % (amount_rounded), + ] + test_result = min(amounts_str, key=len) + + # check result and do another run if necessary + if test_result == result: + return result + elif not result or len(test_result) <= len(result): + digits = digits + 1 + result = test_result + else: + return result + def to_json(self): return self.__repr__()