demurrage.py (2738B)
1 # standard imports 2 import logging 3 import datetime 4 import math 5 6 # eternal imports 7 from chainlib.eth.constant import ZERO_ADDRESS 8 9 # local imports 10 from .token import DemurrageToken 11 12 logg = logging.getLogger(__name__) 13 14 15 class DemurrageCalculator: 16 17 def __init__(self, interest_f_minute): 18 19 self.r_min = interest_f_minute 20 self.r_hour = 1 - ((1 -self.r_min) ** 60) 21 self.r_day = 1 - ((1 -self.r_hour) ** 24) 22 #self.r_week = interest_f_day ** 7 23 logg.info('demurrage calculator set with min {:.32f} hour {:.32f} day {:.32f}'.format(self.r_min, self.r_hour, self.r_day)) 24 25 26 def amount_since(self, amount, timestamp): 27 delta = datetime.datetime.utcnow() - datetime.datetime.fromtimestamp(timestamp) 28 adjusted_amount = amount * ((1 - self.r_day) ** (delta.days)) 29 logg.debug('adjusted for {} days {} -> {}'.format(delta.days, amount, adjusted_amount)) 30 31 remainder = delta.seconds 32 remainder_hours = math.floor(remainder / (60 * 60)) 33 adjusted_delta = adjusted_amount * ((1 - self.r_hour) ** remainder_hours) 34 adjusted_amount -= (adjusted_amount - adjusted_delta) 35 logg.debug('adjusted for {} hours {} -> {} delta {}'.format(remainder_hours, amount, adjusted_amount, adjusted_delta)) 36 37 remainder -= (remainder_hours * (60 * 60)) 38 remainder_minutes = math.floor(remainder / 60) 39 adjusted_delta = adjusted_amount * ((1 - self.r_min) ** remainder_minutes) 40 adjusted_amount -= (adjusted_amount - adjusted_delta) 41 logg.debug('adjusted for {} minutes {} -> {} delta {}'.format(remainder_minutes, amount, adjusted_amount, adjusted_delta)) 42 43 return adjusted_amount 44 45 46 def amount_since_slow(self, amount, timestamp): 47 delta = datetime.datetime.utcnow() - datetime.datetime.fromtimestamp(timestamp) 48 remainder_minutes = math.floor(delta.total_seconds() / 60) 49 adjusted_amount = amount * ((1 - self.r_min) ** remainder_minutes) 50 logg.debug('adjusted for {} minutes {} -> {} delta {}'.format(remainder_minutes, amount, adjusted_amount, amount - adjusted_amount)) 51 52 return adjusted_amount 53 54 55 @staticmethod 56 def from_contract(rpc, chain_spec, contract_address, sender_address=ZERO_ADDRESS): 57 c = DemurrageToken(chain_spec) 58 o = c.tax_level(contract_address, sender_address=sender_address) 59 r = rpc.do(o) 60 taxlevel_i = c.parse_tax_level(r) 61 62 o = c.resolution_factor(contract_address, sender_address=sender_address) 63 r = rpc.do(o) 64 divider = c.parse_resolution_factor(r) 65 logg.debug('taxlevel {} f {}'.format(taxlevel_i, divider)) 66 taxlevel_f = taxlevel_i / divider 67 return DemurrageCalculator(taxlevel_f)