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