evm-booking

EVM smart contract for ERC20 backed time slot booking
Info | Log | Files | Refs | README

booking.py (5249B)


      1 # standard imports
      2 import logging
      3 import os
      4 import enum
      5 
      6 # external imports
      7 from chainlib.eth.constant import ZERO_ADDRESS
      8 from chainlib.eth.contract import (
      9     ABIContractEncoder,
     10     ABIContractDecoder,
     11     ABIContractType,
     12     abi_decode_single,
     13 )
     14 from chainlib.eth.jsonrpc import to_blockheight_param
     15 from chainlib.eth.error import RequestMismatchException
     16 from chainlib.eth.tx import (
     17     TxFactory,
     18     TxFormat,
     19 )
     20 from chainlib.jsonrpc import JSONRPCRequest
     21 from chainlib.block import BlockSpec
     22 from hexathon import (
     23     add_0x,
     24     strip_0x,
     25 )
     26 from chainlib.eth.cli.encode import CLIEncoder
     27 from eth_writer import EthWriter
     28 from eth_expire import EthExpire
     29 
     30 # local imports
     31 from evm_booking.data import data_dir
     32 
     33 logg = logging.getLogger()
     34 
     35 
     36 
     37 class Booking(EthWriter, EthExpire):
     38 
     39     __abi = None
     40     __bytecode = None
     41 
     42     def constructor(self, sender_address, token_address, cap, expiry, tx_format=TxFormat.JSONRPC, version=None):
     43         code = self.cargs(token_address, cap, expiry, version=version)
     44         tx = self.template(sender_address, None, use_nonce=True)
     45         tx = self.set_code(tx, code)
     46         return self.finalize(tx, tx_format)
     47 
     48 
     49     @staticmethod
     50     def cargs(token_address, cap, expiry, version=None):
     51         expiry_timestamp = int(expiry.timestamp())
     52         code = Booking.bytecode(version=version)
     53         enc = ABIContractEncoder()
     54         enc.address(token_address)
     55         enc.uint256(cap)
     56         enc.uint256(expiry_timestamp)
     57         args = enc.get()
     58         code += args
     59         logg.debug('constructor code: ' + args)
     60         return code
     61 
     62 
     63     @staticmethod
     64     def gas(code=None):
     65         return 4000000
     66 
     67 
     68     @staticmethod
     69     def abi():
     70         if Booking.__abi == None:
     71             f = open(os.path.join(data_dir, 'Booking.json'), 'r')
     72             Booking.__abi = json.load(f)
     73             f.close()
     74         return Booking.__abi
     75 
     76 
     77     @staticmethod
     78     def bytecode(version=None):
     79         if Booking.__bytecode == None:
     80             f = open(os.path.join(data_dir, 'Booking.bin'))
     81             Booking.__bytecode = f.read()
     82             f.close()
     83         return Booking.__bytecode
     84 
     85     
     86     def consume(self, contract_address, sender_address, offset, count, tx_format=TxFormat.JSONRPC, id_generator=None):
     87         enc = ABIContractEncoder()
     88         enc.method('consume')
     89         enc.typ(ABIContractType.UINT256)
     90         enc.typ(ABIContractType.UINT256)
     91         enc.uint256(offset)
     92         enc.uint256(count)
     93         data = add_0x(enc.get())
     94         tx = self.template(sender_address, contract_address, use_nonce=True)
     95         tx = self.set_code(tx, data)
     96         tx = self.finalize(tx, tx_format, id_generator=id_generator)
     97         return tx
     98 
     99     
    100     def share(self, contract_address, sender_address, offset, count, tx_format=TxFormat.JSONRPC, id_generator=None):
    101         enc = ABIContractEncoder()
    102         enc.method('share')
    103         enc.typ(ABIContractType.UINT256)
    104         enc.typ(ABIContractType.UINT256)
    105         enc.uint256(offset)
    106         enc.uint256(count)
    107         data = add_0x(enc.get())
    108         tx = self.template(sender_address, contract_address, use_nonce=True)
    109         tx = self.set_code(tx, data)
    110         tx = self.finalize(tx, tx_format, id_generator=id_generator)
    111         return tx
    112 
    113 
    114     def deposit(self, contract_address, sender_address, tx_format=TxFormat.JSONRPC, id_generator=None):
    115         enc = ABIContractEncoder()
    116         enc.method('deposit')
    117         data = add_0x(enc.get())
    118         tx = self.template(sender_address, contract_address, use_nonce=True)
    119         tx = self.set_code(tx, data)
    120         tx = self.finalize(tx, tx_format, id_generator=id_generator)
    121         return tx
    122 
    123 
    124     def raw(self, contract_address, count=0, offset=0, sender_address=ZERO_ADDRESS, id_generator=None, height=BlockSpec.LATEST):
    125         j = JSONRPCRequest(id_generator)
    126         o = j.template()
    127         o['method'] = 'eth_call'
    128         enc = ABIContractEncoder()
    129         enc.method('raw')
    130         enc.typ(ABIContractType.UINT256)
    131         enc.typ(ABIContractType.UINT256)
    132         enc.uint256(count)
    133         enc.uint256(offset)
    134         data = add_0x(enc.get())
    135         tx = self.template(sender_address, contract_address)
    136         tx = self.set_code(tx, data)
    137         o['params'].append(self.normalize(tx))
    138         height = to_blockheight_param(height)
    139         o['params'].append(height)
    140         o = j.finalize(o)
    141         return o
    142 
    143 
    144     def capacity(self, contract_address, sender_address=ZERO_ADDRESS, id_generator=None, height=BlockSpec.LATEST):
    145         j = JSONRPCRequest(id_generator)
    146         o = j.template()
    147         o['method'] = 'eth_call'
    148         enc = ABIContractEncoder()
    149         enc.method('capacity')
    150         data = add_0x(enc.get())
    151         tx = self.template(sender_address, contract_address)
    152         tx = self.set_code(tx, data)
    153         o['params'].append(self.normalize(tx))
    154         height = to_blockheight_param(height)
    155         o['params'].append(height)
    156         o = j.finalize(o)
    157         return o
    158 
    159 
    160     @classmethod
    161     def parse_raw(self, v):
    162         v = strip_0x(v)
    163         l = int(v[64:128], 16)
    164         b = bytes.fromhex(v[128:])
    165         c = 0
    166         r = b''
    167         while c < l:
    168             vv = b[c:c+32]
    169             r += vv
    170             c += 32
    171         return r[:l].hex()