diff --git a/python/CHANGELOG b/python/CHANGELOG index 3602f2b..8f54da5 100644 --- a/python/CHANGELOG +++ b/python/CHANGELOG @@ -1,3 +1,7 @@ +- 0.1.1 + * Settable demurrage steps for apply demurrage cli tool +- 0.1.0 + * Dependency upgrades - 0.0.11 * Apply demurrage cli tool - 0.0.10 diff --git a/python/erc20_demurrage_token/runnable/apply.py b/python/erc20_demurrage_token/runnable/apply.py index 91008fb..270c0f4 100644 --- a/python/erc20_demurrage_token/runnable/apply.py +++ b/python/erc20_demurrage_token/runnable/apply.py @@ -11,6 +11,8 @@ import os import json import argparse import logging +import datetime +import math # external imports import confini @@ -25,10 +27,16 @@ from chainlib.eth.gas import ( RPCGasOracle, OverrideGasOracle, ) +from chainlib.eth.block import ( + block_latest, + block_by_number, + Block, + ) from chainlib.eth.connection import EthHTTPConnection from chainlib.eth.tx import receipt from chainlib.eth.constant import ZERO_ADDRESS import chainlib.eth.cli +from hexathon import to_int as hex_to_int # local imports import erc20_demurrage_token @@ -47,8 +55,11 @@ config_dir = os.path.join(data_dir, 'config') arg_flags = chainlib.eth.cli.argflag_std_write | chainlib.eth.cli.Flag.EXEC argparser = chainlib.eth.cli.ArgumentParser(arg_flags) +argparser.add_argument('--steps', type=int, default=0, help='Max demurrage steps to apply per round') args = argparser.parse_args() config = chainlib.eth.cli.Config.from_args(args, arg_flags, default_fee_limit=DemurrageToken.gas(), base_config_dir=config_dir) +config.add(args.steps, '_STEPS', False) +logg.debug('config loaded:\n{}'.format(config)) wallet = chainlib.eth.cli.Wallet() wallet.from_config(config) @@ -60,30 +71,73 @@ chain_spec = ChainSpec.from_chain_str(config.get('CHAIN_SPEC')) def main(): - signer = rpc.get_signer() - signer_address = rpc.get_sender_address() + o = block_latest() + r = conn.do(o) + + block_start_number = None + try: + block_start_number = hex_to_int(r) + except TypeError: + block_start_number = int(r) + + o = block_by_number(block_start_number) + r = conn.do(o) + + block_start = Block(r) + block_start_timestamp = block_start.timestamp + block_start_datetime = datetime.datetime.fromtimestamp(block_start_timestamp) gas_oracle = rpc.get_gas_oracle() - nonce_oracle = rpc.get_nonce_oracle() + c = DemurrageToken(chain_spec, gas_oracle=gas_oracle) + o = c.demurrage_timestamp(config.get('_EXEC_ADDRESS')) + r = conn.do(o) - c = DemurrageToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) - (tx_hash_hex, o) = c.apply_demurrage(config.get('_EXEC_ADDRESS'), signer_address) - if config.get('_RPC_SEND'): - conn.do(o) - if config.get('_WAIT'): - r = conn.wait(tx_hash_hex) - if r['status'] == 0: - sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you') - sys.exit(1) - # TODO: pass through translator for keys (evm tester uses underscore instead of camelcase) - address = r['contractAddress'] + demurrage_timestamp = None + try: + demurrage_timestamp = hex_to_int(r) + except TypeError: + demurrage_timestamp = int(r) + demurrage_datetime = datetime.datetime.fromtimestamp(demurrage_timestamp) - print(address) - else: + total_seconds = block_start_timestamp - demurrage_timestamp + total_steps = total_seconds / 60 + + if total_steps < 1.0: + logg.error('only {} seconds since last demurrage application, skipping'.format(total_seconds)) + return + + logg.debug('block start is at {} demurrage is at {} -> {} minutes'.format( + block_start_datetime, + demurrage_datetime, + total_steps, + )) + + rounds = 1 + if config.get('_STEPS') > 0: + rounds = math.ceil(total_steps / config.get('_STEPS')) + + logg.info('will perform {} rounds of {} steps'.format(rounds, config.get('_STEPS'))) + + last_tx_hash = None + for i in range(rounds): + signer = rpc.get_signer() + signer_address = rpc.get_sender_address() + + nonce_oracle = rpc.get_nonce_oracle() + + c = DemurrageToken(chain_spec, signer=signer, gas_oracle=gas_oracle, nonce_oracle=nonce_oracle) + (tx_hash_hex, o) = c.apply_demurrage(config.get('_EXEC_ADDRESS'), signer_address, limit=config.get('_STEPS')) + if config.get('_RPC_SEND'): print(tx_hash_hex) + conn.do(o) + if config.get('_WAIT_ALL') or (i == rounds - 1 and config.get('_WAIT')): + r = conn.wait(tx_hash_hex) + if r['status'] == 0: + sys.stderr.write('EVM revert while deploying contract. Wish I had more to tell you') + sys.exit(1) + else: + print(o) - else: - print(o) if __name__ == '__main__': diff --git a/python/erc20_demurrage_token/token.py b/python/erc20_demurrage_token/token.py index 4b16df8..f1397f0 100644 --- a/python/erc20_demurrage_token/token.py +++ b/python/erc20_demurrage_token/token.py @@ -380,6 +380,10 @@ class DemurrageToken(ERC20): return self.call_noarg('demurrageAmount', contract_address, sender_address=sender_address) + def demurrage_timestamp(self, contract_address, sender_address=ZERO_ADDRESS): + return self.call_noarg('demurrageTimestamp', contract_address, sender_address=sender_address) + + def supply_cap(self, contract_address, sender_address=ZERO_ADDRESS): return self.call_noarg('supplyCap', contract_address, sender_address=sender_address) diff --git a/python/setup.cfg b/python/setup.cfg index 673d811..dd9ec7d 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = erc20-demurrage-token -version = 0.1.0 +version = 0.1.1 description = ERC20 token with redistributed continual demurrage author = Louis Holbrook author_email = dev@holbrook.no @@ -25,12 +25,13 @@ licence_files = [options] include_package_data = True -python_requires = >= 3.6 +python_requires = >= 3.7 packages = erc20_demurrage_token erc20_demurrage_token.runnable erc20_demurrage_token.data erc20_demurrage_token.sim + erc20_demurrage_token.unittest [options.package_data] * =