encode.py (2801B)
1 # standard imports 2 import re 3 import logging 4 5 # external imports 6 from chainlib.eth.contract import ( 7 ABIContractType, 8 ABIContractEncoder, 9 ) 10 from chainlib.eth.constant import ZERO_ADDRESS 11 from chainlib.eth.constant import ZERO_CONTENT 12 13 logg = logging.getLogger(__name__) 14 15 16 class CLIEncoder(ABIContractEncoder): 17 18 __re_uint = r'^([uU])[int]*([0-9]+)?$' 19 __re_bytes = r'^([bB])[ytes]*([0-9]+)?$' 20 __re_string = r'^([sS])[tring]*$' 21 __re_address = r'^([aA])[ddress]*?$' 22 __translations = [ 23 'to_uint', 24 'to_bytes', 25 'to_string', 26 'to_address', 27 ] 28 29 def __init__(self, signature=None): 30 super(CLIEncoder, self).__init__() 31 self.signature = signature 32 if signature != None: 33 self.method(signature) 34 35 def to_uint(self, typ): 36 s = None 37 a = None 38 m = re.match(self.__re_uint, typ) 39 if m == None: 40 return None 41 42 n = m.group(2) 43 if m.group(2) == None: 44 n = 256 45 s = 'UINT256'.format(m.group(2)) 46 a = getattr(ABIContractType, s) 47 return (s, a) 48 49 50 def to_bytes(self, typ): 51 s = None 52 a = None 53 m = re.match(self.__re_bytes, typ) 54 if m == None: 55 return None 56 57 n = m.group(2) 58 if n == None: 59 n = 32 60 s = 'BYTES{}'.format(n) 61 a = getattr(ABIContractType, s) 62 return (s, a) 63 64 65 def to_address(self, typ): 66 s = None 67 a = None 68 m = re.match(self.__re_address, typ) 69 if m == None: 70 return None 71 72 s = 'ADDRESS' 73 a = getattr(ABIContractType, s) 74 return (s, a) 75 76 77 def to_string(self, typ): 78 m = re.match(self.__re_string, typ) 79 if m == None: 80 return None 81 s = 'STRING' 82 a = getattr(ABIContractType, s) 83 return (s, a) 84 85 86 def translate(self, typ, val): 87 r = None 88 for tr in self.__translations: 89 r = getattr(self, tr)(typ) 90 if r != None: 91 break 92 if r == None: 93 raise ValueError('no translation for type {}'.format(typ)) 94 logg.debug('type {} translated to {}'.format(typ, r[0])) 95 if r[0] != 'STRING': 96 if int(val, 16) == 0: 97 if r[0][0] == 'B': 98 val = ZERO_CONTENT 99 elif r[0][0] == 'A': 100 val = ZERO_ADDRESS 101 return (r[1], val,) 102 103 104 def add_from(self, arg): 105 logg.debug('arg {}'.format(arg)) 106 (typ, val) = arg.split(':', maxsplit=1) 107 (real_typ, val) = self.translate(typ, val) 108 if self.signature != None: 109 self.typ(real_typ) 110 fn = getattr(self, real_typ.value) 111 fn(val)