chainlib-eth

Ethereum implementation of the chainlib interface
Info | Log | Files | Refs | README | LICENSE

gas.py (6095B)


      1 # SPDX-License-Identifier: GPL-3.0-or-later
      2 
      3 # standard imports
      4 import io
      5 import sys
      6 import os
      7 import json
      8 import argparse
      9 import logging
     10 import urllib
     11 
     12 # external imports
     13 from hexathon import (
     14         add_0x,
     15         strip_0x,
     16         )
     17 from chainlib.settings import ChainSettings
     18 from chainlib.jsonrpc import (
     19         JSONRPCRequest,
     20         IntSequenceGenerator,
     21         )
     22 from chainlib.chain import ChainSpec
     23 
     24 # local imports
     25 from chainlib.eth.address import to_checksum_address
     26 from chainlib.eth.connection import EthHTTPConnection
     27 from chainlib.eth.gas import Gas
     28 from chainlib.eth.gas import balance as gas_balance
     29 from chainlib.eth.cli.decode import decode_for_puny_humans
     30 from chainlib.eth.address import (
     31         is_same_address,
     32         is_checksum_address,
     33         )
     34 import chainlib.eth.cli
     35 from chainlib.eth.cli.arg import (
     36         Arg,
     37         ArgFlag,
     38         process_args,
     39         )
     40 from chainlib.eth.cli.config import (
     41         Config,
     42         process_config,
     43         )
     44 from chainlib.eth.cli.log import process_log
     45 from chainlib.eth.settings import process_settings
     46 
     47 logg = logging.getLogger()
     48 
     49 
     50 def from_data_arg(data):
     51     try:
     52         data = strip_0x(data)
     53         logg.info('appended input hex data: {}'.format(data))
     54         return data
     55     except ValueError:
     56         pass
     57 
     58     filename = data
     59     try:
     60         f = open(filename, 'r')
     61     except:
     62         raise ValueError("data not hex and not file we can open")
     63 
     64     data = f.read()
     65     f.close()
     66     logg.info('appended input data from file {}: {}'.format(filename, data))
     67 
     68     data = data.rstrip()
     69     return strip_0x(data)
     70 
     71 
     72 def process_config_local(config, arg, args, flags):
     73     data = ''
     74     if args.data != None:
     75         for data_arg in args.data:
     76             data += from_data_arg(data_arg)
     77     if data == '':
     78         data = None
     79     config.add(data, '_DATA', False)
     80     config.add(args.amount[0], '_VALUE', False)
     81     return config
     82 
     83 
     84 arg_flags = ArgFlag()
     85 arg = Arg(arg_flags)
     86 flags = arg_flags.STD_WRITE | arg_flags.WALLET | arg_flags.VALUE | arg_flags.TAB
     87 
     88 argparser = chainlib.eth.cli.ArgumentParser()
     89 argparser = process_args(argparser, arg, flags)
     90 argparser.add_argument('--data', type=str, action='append', help='Transaction data')
     91 argparser.add_argument('amount', type=str, help='Token amount to send')
     92 args = argparser.parse_args()
     93 
     94 logg = process_log(args, logg)
     95 
     96 config = Config()
     97 config = process_config(config, arg, args, flags, positional_name='amount')
     98 config = process_config_local(config, arg, args, flags)
     99 logg.debug('config loaded:\n{}'.format(config))
    100 
    101 settings = ChainSettings()
    102 settings = process_settings(settings, config)
    103 logg.debug('settings loaded:\n{}'.format(settings))
    104 
    105 
    106 def balance(conn, address, id_generator):
    107     o = gas_balance(address, id_generator=id_generator)
    108     r = conn.do(o)
    109     try:
    110         balance = int(r)
    111     except ValueError:
    112         balance = strip_0x(r)
    113         balance = int(balance, 16)
    114     return balance
    115 
    116 
    117 def main():
    118     g = Gas(
    119             settings.get('CHAIN_SPEC'),
    120             signer=settings.get('SIGNER'),
    121             gas_oracle=settings.get('FEE_ORACLE'),
    122             nonce_oracle=settings.get('NONCE_ORACLE'),
    123             )
    124 
    125     recipient = settings.get('RECIPIENT')
    126 
    127     if logg.isEnabledFor(logging.DEBUG):
    128         try:
    129             sender_balance = balance(
    130                     settings.get('CONN'),
    131                     settings.get('SENDER_ADDRESS'),
    132                     settings.get('RPC_ID_GENERATOR'),
    133                     )
    134             logg.debug('sender {} balance before: {}'.format(settings.get('SENDER_ADDRESS'), sender_balance))
    135             if settings.get('RECIPIENT') != None:
    136                 recipient_balance = balance(
    137                         settings.get('CONN'),
    138                         settings.get('RECIPIENT'),
    139                         settings.get('RPC_ID_GENERATOR'),
    140                         )
    141                 logg.debug('recipient {} balance before: {}'.format(settings.get('RECIPIENT'), recipient_balance))
    142         except urllib.error.URLError:
    143             pass
    144      
    145     (tx_hash_hex, o) = g.create(
    146             settings.get('SENDER_ADDRESS'),
    147             recipient,
    148             settings.get('VALUE'),
    149             data=settings.get('DATA'),
    150             id_generator=settings.get('RPC_ID_GENERATOR'),
    151         )
    152     
    153     logg.info('gas transfer from {} to {} value {} hash {}'.format(settings.get('SENDER_ADDRESS'), settings.get('RECIPIENT'), settings.get('VALUE'), tx_hash_hex))
    154 
    155     if settings.get('RPC_SEND'):
    156         settings.get('CONN').do(o)
    157         if config.true('_WAIT'):
    158             r = settings.get('CONN').wait(tx_hash_hex)
    159             if logg.isEnabledFor(logging.DEBUG):
    160                 sender_balance = balance(
    161                         settings.get('CONN'),
    162                         settings.get('SENDER_ADDRESS'),
    163                         settings.get('RPC_ID_GENERATOR'),
    164                         )
    165                 logg.debug('sender {} balance before: {}'.format(settings.get('SENDER_ADDRESS'), sender_balance))
    166                 if settings.get('RECIPIENT') != None:
    167                     recipient_balance = balance(
    168                             settings.get('CONN'),
    169                             settings.get('RECIPIENT'),
    170                             settings.get('RPC_ID_GENERATOR'),
    171                             )
    172                     logg.debug('recipient {} balance before: {}'.format(settings.get('RECIPIENT'), recipient_balance))
    173             if r['status'] == 0:
    174                 logg.critical('VM revert for {}. Wish I could tell you more'.format(tx_hash_hex))
    175                 sys.exit(1)
    176         print(tx_hash_hex)
    177     else:
    178         if config.true('_RAW'):
    179             print(o['params'][0])
    180         else:
    181             io_str = io.StringIO()
    182             decode_for_puny_humans(
    183                     o['params'][0],
    184                     settings.get('CHAIN_SPEC'),
    185                     io_str,
    186                     fields=config.get('_OUTARG'),
    187                     skip_keys=config.true('_RAW'),
    188                     )
    189             sys.stdout.write(io_str.getvalue())
    190  
    191 
    192 
    193 if __name__ == '__main__':
    194     main()