erc20.py (8888B)
1 # standard imports 2 import logging 3 4 # external imports 5 from chainlib.eth.constant import ZERO_ADDRESS 6 from chainlib.eth.contract import ( 7 ABIContractEncoder, 8 ABIContractDecoder, 9 ABIContractType, 10 abi_decode_single, 11 ) 12 from chainlib.eth.jsonrpc import to_blockheight_param 13 from chainlib.eth.error import RequestMismatchException 14 from chainlib.eth.tx import ( 15 TxFactory, 16 TxFormat, 17 ) 18 from chainlib.jsonrpc import JSONRPCRequest 19 from chainlib.block import BlockSpec 20 from hexathon import ( 21 add_0x, 22 strip_0x, 23 ) 24 25 logg = logging.getLogger() 26 27 28 class ERC20(TxFactory): 29 30 31 def balance_of(self, contract_address, address, sender_address=ZERO_ADDRESS, id_generator=None, height=BlockSpec.LATEST): 32 j = JSONRPCRequest(id_generator) 33 o = j.template() 34 o['method'] = 'eth_call' 35 enc = ABIContractEncoder() 36 enc.method('balanceOf') 37 enc.typ(ABIContractType.ADDRESS) 38 enc.address(address) 39 data = add_0x(enc.get()) 40 tx = self.template(sender_address, contract_address) 41 tx = self.set_code(tx, data) 42 o['params'].append(self.normalize(tx)) 43 height = to_blockheight_param(height) 44 o['params'].append(height) 45 o = j.finalize(o) 46 return o 47 48 49 def balance(self, contract_address, address, sender_address=ZERO_ADDRESS, id_generator=None): 50 return self.balance_of(contract_address, address, sender_address=sender_address, id_generator=id_generator) 51 52 53 def symbol(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None): 54 j = JSONRPCRequest(id_generator) 55 o = j.template() 56 o['method'] = 'eth_call' 57 enc = ABIContractEncoder() 58 enc.method('symbol') 59 data = add_0x(enc.get()) 60 tx = self.template(sender_address, contract_address) 61 tx = self.set_code(tx, data) 62 o['params'].append(self.normalize(tx)) 63 o['params'].append('latest') 64 o = j.finalize(o) 65 return o 66 67 68 def name(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None): 69 j = JSONRPCRequest(id_generator) 70 o = j.template() 71 o['method'] = 'eth_call' 72 enc = ABIContractEncoder() 73 enc.method('name') 74 data = add_0x(enc.get()) 75 tx = self.template(sender_address, contract_address) 76 tx = self.set_code(tx, data) 77 o['params'].append(self.normalize(tx)) 78 o['params'].append('latest') 79 o = j.finalize(o) 80 return o 81 82 83 def decimals(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None): 84 j = JSONRPCRequest(id_generator) 85 o = j.template() 86 o['method'] = 'eth_call' 87 enc = ABIContractEncoder() 88 enc.method('decimals') 89 data = add_0x(enc.get()) 90 tx = self.template(sender_address, contract_address) 91 tx = self.set_code(tx, data) 92 o['params'].append(self.normalize(tx)) 93 o['params'].append('latest') 94 o = j.finalize(o) 95 return o 96 97 98 def total_supply(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None): 99 j = JSONRPCRequest(id_generator) 100 o = j.template() 101 o['method'] = 'eth_call' 102 enc = ABIContractEncoder() 103 enc.method('totalSupply') 104 data = add_0x(enc.get()) 105 tx = self.template(sender_address, contract_address) 106 tx = self.set_code(tx, data) 107 o['params'].append(self.normalize(tx)) 108 o['params'].append('latest') 109 o = j.finalize(o) 110 return o 111 112 113 def allowance(self, contract_address, holder_address, spender_address, sender_address=ZERO_ADDRESS, id_generator=None): 114 j = JSONRPCRequest(id_generator) 115 o = j.template() 116 o['method'] = 'eth_call' 117 enc = ABIContractEncoder() 118 enc.method('allowance') 119 enc.typ(ABIContractType.ADDRESS) 120 enc.typ(ABIContractType.ADDRESS) 121 enc.address(holder_address) 122 enc.address(spender_address) 123 data = add_0x(enc.get()) 124 tx = self.template(sender_address, contract_address) 125 tx = self.set_code(tx, data) 126 o['params'].append(self.normalize(tx)) 127 o['params'].append('latest') 128 o = j.finalize(o) 129 return o 130 131 132 def transfer(self, contract_address, sender_address, recipient_address, value, tx_format=TxFormat.JSONRPC, id_generator=None): 133 enc = ABIContractEncoder() 134 enc.method('transfer') 135 enc.typ(ABIContractType.ADDRESS) 136 enc.typ(ABIContractType.UINT256) 137 enc.address(recipient_address) 138 enc.uint256(value) 139 data = add_0x(enc.get()) 140 tx = self.template(sender_address, contract_address, use_nonce=True) 141 tx = self.set_code(tx, data) 142 tx = self.finalize(tx, tx_format, id_generator=id_generator) 143 return tx 144 145 146 def transfer_from(self, contract_address, sender_address, holder_address, recipient_address, value, tx_format=TxFormat.JSONRPC, id_generator=None): 147 enc = ABIContractEncoder() 148 enc.method('transferFrom') 149 enc.typ(ABIContractType.ADDRESS) 150 enc.typ(ABIContractType.ADDRESS) 151 enc.typ(ABIContractType.UINT256) 152 enc.address(holder_address) 153 enc.address(recipient_address) 154 enc.uint256(value) 155 data = add_0x(enc.get()) 156 tx = self.template(sender_address, contract_address, use_nonce=True) 157 tx = self.set_code(tx, data) 158 tx = self.finalize(tx, tx_format) 159 return tx 160 161 162 def approve(self, contract_address, sender_address, spender_address, value, tx_format=TxFormat.JSONRPC, id_generator=None): 163 enc = ABIContractEncoder() 164 enc.method('approve') 165 enc.typ(ABIContractType.ADDRESS) 166 enc.typ(ABIContractType.UINT256) 167 enc.address(spender_address) 168 enc.uint256(value) 169 data = add_0x(enc.get()) 170 tx = self.template(sender_address, contract_address, use_nonce=True) 171 tx = self.set_code(tx, data) 172 tx = self.finalize(tx, tx_format) 173 return tx 174 175 176 @classmethod 177 def parse_symbol(self, v): 178 return abi_decode_single(ABIContractType.STRING, v) 179 180 181 @classmethod 182 def parse_name(self, v): 183 return abi_decode_single(ABIContractType.STRING, v) 184 185 186 @classmethod 187 def parse_decimals(self, v): 188 return abi_decode_single(ABIContractType.UINT256, v) 189 190 191 @classmethod 192 def parse_balance(self, v): 193 return abi_decode_single(ABIContractType.UINT256, v) 194 195 196 @classmethod 197 def parse_balance_of(self, v): 198 return self.parse_balance(v) 199 200 201 @classmethod 202 def parse_total_supply(self, v): 203 return abi_decode_single(ABIContractType.UINT256, v) 204 205 206 @classmethod 207 def parse_allowance(self, v): 208 return abi_decode_single(ABIContractType.UINT256, v) 209 210 211 @classmethod 212 def parse_transfer_request(self, v): 213 v = strip_0x(v) 214 cursor = 0 215 enc = ABIContractEncoder() 216 enc.method('transfer') 217 enc.typ(ABIContractType.ADDRESS) 218 enc.typ(ABIContractType.UINT256) 219 r = enc.get() 220 l = len(r) 221 m = v[:l] 222 if m != r: 223 raise RequestMismatchException(v) 224 cursor += l 225 226 dec = ABIContractDecoder() 227 dec.typ(ABIContractType.ADDRESS) 228 dec.typ(ABIContractType.UINT256) 229 dec.val(v[cursor:cursor+64]) 230 cursor += 64 231 dec.val(v[cursor:cursor+64]) 232 r = dec.decode() 233 return r 234 235 236 @classmethod 237 def parse_transfer_from_request(self, v): 238 v = strip_0x(v) 239 cursor = 0 240 enc = ABIContractEncoder() 241 enc.method('transferFrom') 242 enc.typ(ABIContractType.ADDRESS) 243 enc.typ(ABIContractType.ADDRESS) 244 enc.typ(ABIContractType.UINT256) 245 r = enc.get() 246 l = len(r) 247 m = v[:l] 248 if m != r: 249 raise RequestMismatchException(v) 250 cursor += l 251 252 dec = ABIContractDecoder() 253 dec.typ(ABIContractType.ADDRESS) 254 dec.typ(ABIContractType.ADDRESS) 255 dec.typ(ABIContractType.UINT256) 256 dec.val(v[cursor:cursor+64]) 257 cursor += 64 258 dec.val(v[cursor:cursor+64]) 259 cursor += 64 260 dec.val(v[cursor:cursor+64]) 261 r = dec.decode() 262 return r 263 264 265 @classmethod 266 def parse_approve_request(self, v): 267 v = strip_0x(v) 268 cursor = 0 269 enc = ABIContractEncoder() 270 enc.method('approve') 271 enc.typ(ABIContractType.ADDRESS) 272 enc.typ(ABIContractType.UINT256) 273 r = enc.get() 274 l = len(r) 275 m = v[:l] 276 if m != r: 277 raise RequestMismatchException(v) 278 cursor += l 279 280 dec = ABIContractDecoder() 281 dec.typ(ABIContractType.ADDRESS) 282 dec.typ(ABIContractType.UINT256) 283 dec.val(v[cursor:cursor+64]) 284 cursor += 64 285 dec.val(v[cursor:cursor+64]) 286 r = dec.decode() 287 return r