settings.py (5717B)
1 # standard imports 2 import logging 3 4 # external imports 5 from chainlib.settings import process_settings as base_process_settings 6 from chainlib.error import SignerMissingException 7 from hexathon import ( 8 add_0x, 9 strip_0x, 10 ) 11 from chainlib.block import BlockSpec 12 13 # local imports 14 import chainlib.eth.cli 15 from chainlib.eth.address import to_checksum_address 16 from chainlib.eth.constant import ZERO_ADDRESS 17 18 logg = logging.getLogger(__name__) 19 20 21 def process_settings_rpc(settings, config): 22 rpc = chainlib.eth.cli.Rpc(settings.get('WALLET')) 23 conn = rpc.connect_by_config(config, nonce_confirmed=True) 24 25 settings.set('CONN', conn) 26 settings.set('RPC_ID_GENERATOR', rpc.id_generator) 27 settings.set('RPC_SEND', config.true('_RPC_SEND')) 28 settings.set('WAIT', config.true('_WAIT')) 29 30 gas_oracle = rpc.get_gas_oracle() 31 settings.set('GAS_ORACLE', gas_oracle) 32 settings.set('FEE_ORACLE', gas_oracle) 33 34 sender_address = rpc.get_sender_address() 35 try: 36 settings.set('SIGNER', rpc.get_signer()) 37 except AttributeError: 38 pass 39 except SignerMissingException: 40 pass 41 42 settings.set('SENDER_ADDRESS', add_0x(sender_address)) 43 44 nonce_oracle = rpc.get_nonce_oracle() 45 settings.set('NONCE_ORACLE', nonce_oracle) 46 47 return settings 48 49 50 def process_settings_blockspec(settings, config): 51 blockspec_in = None 52 try: 53 blockspec_in = config.get('_HEIGHT') 54 except KeyError: 55 return settings 56 57 blockspec = None 58 if blockspec_in == 'latest': 59 blockspec = BlockSpec.LATEST 60 elif blockspec_in == 'pending': 61 blockspec = BlockSpec.PENDING 62 else: 63 blockspec = int(blockspec_in) 64 65 settings.set('HEIGHT', blockspec) 66 67 return settings 68 69 70 def __try_zero_address(config, address): 71 try: 72 if int(address) == 0: 73 return ZERO_ADDRESS 74 except ValueError: 75 pass 76 77 try: 78 if int(address, 16) == 0: 79 return ZERO_ADDRESS 80 except ValueError: 81 pass 82 83 recipient = to_checksum_address(address) 84 if not config.true('_UNSAFE') and recipient != address: 85 raise ValueError('invalid checksum address: {}'.format(address)) 86 87 return add_0x(recipient) 88 89 90 def __calculate_net_amount(settings, config): 91 price = settings.get('FEE_PRICE') 92 if price == None: 93 fee_oracle = settings.get('FEE_ORACLE') 94 # TODO: pass on code and input 95 r = fee_oracle.get_fee() 96 price = r[0] 97 98 value = settings.get('VALUE') 99 if config.true('_TOTAL'): 100 delta = config.get('_FEE_LIMIT') * price 101 value -= delta 102 if value < 0: 103 raise ValueError('Resulting value is negative') 104 logg.info('total switch set, adjusting sent amount {} by {} to {}'.format(settings.get('VALUE'), delta, value)) 105 106 return value 107 108 109 def process_settings_wallet(settings, config): 110 wallet = chainlib.eth.cli.Wallet() 111 wallet.from_config(config) 112 113 settings.set('WALLET', wallet) 114 115 try: 116 if config.get('_NULL'): 117 settings.set('RECIPIENT', None) 118 return settings 119 except KeyError: 120 pass 121 122 recipient_in = None 123 try: 124 recipient_in = config.get('_RECIPIENT') 125 except KeyError: 126 return settings 127 128 if recipient_in == None: 129 return settings 130 elif recipient_in == 'null': 131 settings.set('RECIPIENT', None) 132 return settings 133 134 if wallet.get_signer_address() == None and recipient_in != None: 135 recipient_in = wallet.from_address(recipient_in) 136 recipient_in = strip_0x(recipient_in) 137 138 recipient = __try_zero_address(config, recipient_in) 139 140 settings.set('RECIPIENT', recipient) 141 142 return settings 143 144 145 def process_settings_contract(settings, config): 146 exec_address_in = None 147 try: 148 exec_address_in = config.get('_EXEC_ADDRESS') 149 except KeyError: 150 return settings 151 152 if exec_address_in == None: 153 return settings 154 155 exec_address = to_checksum_address(exec_address_in) 156 if not config.true('_UNSAFE') and exec_address != exec_address_in: 157 raise ValueError('invalid checksum address: {}'.format(exec_address_in)) 158 exec_address = add_0x(exec_address) 159 160 settings.set('EXEC', exec_address) 161 return settings 162 163 164 def process_settings_data(settings, config): 165 data = None 166 try: 167 data = config.get('_DATA') 168 except KeyError: 169 settings.set('DATA', None) 170 return settings 171 172 if data == None: 173 return settings 174 175 settings.set('DATA', data) 176 177 return settings 178 179 180 def process_settings_value(settings, config): 181 updated_value = __calculate_net_amount(settings, config) 182 settings.set('VALUE', updated_value) 183 184 return settings 185 186 187 def process_settings_hash(settings, config): 188 hshs = None 189 try: 190 hshs = config.get('_HASH') 191 except KeyError: 192 return settings 193 194 if isinstance(hshs, str): 195 hshs = [hshs] 196 197 r = [] 198 for hsh in hshs: 199 hsh = strip_0x(hsh) 200 l = len(hsh) 201 if l != 64: 202 raise ValueError('invalid hash length {} for {}'.format(l, hsh)) 203 hsh = add_0x(hsh) 204 r.append(hsh) 205 206 settings.set('HASH', r) 207 208 return settings 209 210 211 def process_settings(settings, config): 212 settings = base_process_settings(settings, config) 213 settings = process_settings_wallet(settings, config) 214 settings = process_settings_rpc(settings, config) 215 settings = process_settings_blockspec(settings, config) 216 settings = process_settings_data(settings, config) 217 settings = process_settings_hash(settings, config) 218 settings = process_settings_value(settings, config) 219 settings = process_settings_contract(settings, config) 220 return settings