wait.py (4102B)
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 chainlib.settings import ChainSettings 14 from funga.eth.signer import EIP155Signer 15 from funga.eth.keystore.dict import DictKeystore 16 from chainlib.chain import ChainSpec 17 from chainlib.jsonrpc import ( 18 JSONRPCRequest, 19 IntSequenceGenerator, 20 ) 21 from hexathon import ( 22 add_0x, 23 strip_0x, 24 uniform as hex_uniform, 25 ) 26 27 # local imports 28 from chainlib.eth.address import to_checksum 29 from chainlib.eth.connection import EthHTTPConnection 30 from chainlib.eth.nonce import ( 31 RPCNonceOracle, 32 OverrideNonceOracle, 33 ) 34 from chainlib.eth.gas import ( 35 RPCGasOracle, 36 OverrideGasOracle, 37 ) 38 from chainlib.eth.tx import ( 39 TxFactory, 40 raw, 41 ) 42 from chainlib.eth.error import RevertEthException 43 from chainlib.eth.jsonrpc import to_blockheight_param 44 import chainlib.eth.cli 45 from chainlib.eth.cli.arg import ( 46 Arg, 47 ArgFlag, 48 process_args, 49 stdin_arg, 50 ) 51 from chainlib.eth.cli.config import ( 52 Config, 53 process_config, 54 ) 55 from chainlib.eth.cli.log import process_log 56 from chainlib.eth.settings import process_settings 57 58 logg = logging.getLogger() 59 60 script_dir = os.path.dirname(os.path.realpath(__file__)) 61 config_dir = os.path.join(script_dir, '..', 'data', 'config') 62 63 64 def process_config_local(config, arg, args, flags): 65 config.add(args.ignore, '_IGNORE', False) 66 config.add(args.ignore_all, '_IGNORE_ALL', False) 67 68 hsh = config.get('_POSARG') 69 try: 70 hsh = strip_0x(hsh) 71 except TypeError: 72 hsh = stdin_arg() 73 hsh = strip_0x(hsh) 74 75 config.add(hsh, '_HASH', False) 76 77 return config 78 79 80 def process_settings_local(settings, config): 81 settings.set('HASH', config.get('_HASH')) 82 return settings 83 84 85 arg_flags = ArgFlag() 86 arg = Arg(arg_flags) 87 flags = arg_flags.STD_READ 88 89 argparser = chainlib.eth.cli.ArgumentParser() 90 argparser = process_args(argparser, arg, flags) 91 argparser.add_argument('--ignore', type=str, action='append', default=[], help='Ignore error from the given transaction') 92 argparser.add_argument('--ignore-all', action='store_true', dest='ignore_all', help='Ignore errors from all transactions') 93 argparser.add_argument('hashes', nargs='*', type=str, help='Transaction hashes to wait for') 94 args = argparser.parse_args() 95 96 logg = process_log(args, logg) 97 98 config = Config() 99 config = process_config(config, arg, args, flags, positional_name='hashes') 100 config = process_config_local(config, arg, args, flags) 101 logg.debug('config loaded:\n{}'.format(config)) 102 103 settings = ChainSettings() 104 settings = process_settings(settings, config) 105 logg.debug('settings loaded:\n{}'.format(settings)) 106 107 108 def main(): 109 110 hashes_ready = [] 111 hashes_ignore = [] 112 113 for hsh in config.get('_IGNORE'): 114 hashes_ignore.append(add_0x(hex_uniform(strip_0x(hsh)))) 115 116 if len(settings.get('HASH')) == 1: 117 hsh = settings.get('HASH')[0] 118 try: 119 hashes_ready = [hsh] 120 except ValueError: 121 logg.debug('hash argument not a hash, will try it as a file name') 122 f = open(hsh) 123 for hsh in f: 124 hashes_ready.append(hsh) 125 f.close() 126 else: 127 for hsh in settings.get('HASH'): 128 if hsh in hashes_ready: 129 logg.debug('skipping duplicate hash {}'.format(hsh)) 130 continue 131 hashes_ready.append(hsh) 132 133 for hsh in hashes_ready: 134 logg.info('processing transaction hash {}'.format(hsh)) 135 try: 136 r = settings.get('CONN').wait(hsh) 137 except RevertEthException: 138 if config.get('_IGNORE_ALL') or hsh in hashes_ignore: 139 logg.debug('ignoring revert in transaction hash {}'.format(hsh)) 140 continue 141 sys.stderr.write('revert in transaction hash {}\n'.format(hsh)) 142 sys.exit(1) 143 144 145 if __name__ == '__main__': 146 main()