eth-erc721

ERC-721 'NFT' token interface with example developer badge token contract
Info | Log | Files | Refs | LICENSE

erc721.py (6632B)


      1 # external imports
      2 from chainlib.eth.tx import (
      3         TxFormat,
      4         TxFactory,
      5         )
      6 from chainlib.eth.contract import (
      7         ABIContractEncoder,
      8         ABIContractType,
      9         abi_decode_single,
     10         )
     11 from chainlib.jsonrpc import JSONRPCRequest
     12 from chainlib.eth.constant import ZERO_ADDRESS
     13 from hexathon import (
     14         add_0x,
     15         )
     16 from eth_erc20 import ERC20
     17 from eth_owned import ERC173
     18 
     19 
     20 class ERC721(ERC20, ERC173):
     21 
     22     def transfer(self, contract_address, sender_address, recipient_address, value, tx_format=TxFormat.JSONRPC):
     23         raise NotImplementedError('EIP721 does not implement ERC20.transfer')
     24 
     25 
     26     def set_approve_for_all(self, contract_address, sender_address, operator_address, flag, tx_format=TxFormat.JSONRPC):
     27         enc = ABIContractEncoder()
     28         enc.method('setApprovalForAll')
     29         enc.typ(ABIContractType.ADDRESS)
     30         enc.typ(ABIContractType.BOOLEAN)
     31         enc.address(operator_address)
     32         enc.uint256(int(flag))
     33         data = enc.get()
     34         tx = self.template(sender_address, contract_address, use_nonce=True)
     35         tx = self.set_code(tx, data)
     36         tx = self.finalize(tx, tx_format)
     37         return tx
     38 
     39     
     40     def set_operator(self, contract_address, sender_address, operator_address, tx_format=TxFormat.JSONRPC):
     41         return self.set_approve_for_all(contract_address, sender_address, operator_address, True, tx_format=tx_format)
     42 
     43 
     44     def remove_operator(self, contract_address, sender_address, operator_address, tx_format=TxFormat.JSONRPC):
     45         return self.set_approve_for_all(contract_address, sender_address, operator_address, False, tx_format=tx_format)
     46 
     47 
     48     def token_by_index(self, contract_address, idx, sender_address=ZERO_ADDRESS, id_generator=None):
     49         j = JSONRPCRequest(id_generator)
     50         o = j.template()
     51         o['method'] = 'eth_call'
     52         enc = ABIContractEncoder()
     53         enc.method('tokenByIndex')
     54         enc.typ(ABIContractType.UINT256)
     55         enc.uint256(idx)
     56         data = add_0x(enc.get())
     57         tx = self.template(sender_address, contract_address)
     58         tx = self.set_code(tx, data)
     59         o['params'].append(self.normalize(tx))
     60         o['params'].append('latest')
     61         o = j.finalize(o)
     62         return o
     63 
     64 
     65     def owner_of(self, contract_address, token_id, sender_address=ZERO_ADDRESS, id_generator=None):
     66         j = JSONRPCRequest(id_generator)
     67         o = j.template()
     68         o['method'] = 'eth_call'
     69         enc = ABIContractEncoder()
     70         enc.method('ownerOf')
     71         enc.typ(ABIContractType.UINT256)
     72         enc.uint256(token_id)
     73         data = add_0x(enc.get())
     74         tx = self.template(sender_address, contract_address)
     75         tx = self.set_code(tx, data)
     76         o['params'].append(self.normalize(tx))
     77         o['params'].append('latest')
     78         o = j.finalize(o)
     79         return o
     80 
     81 
     82     def is_approved_for_all(self, contract_address, holder_address, operator_address, sender_address=ZERO_ADDRESS, id_generator=None):
     83         j = JSONRPCRequest(id_generator)
     84         o = j.template()
     85         o['method'] = 'eth_call'
     86         enc = ABIContractEncoder()
     87         enc.method('isApprovedForAll')
     88         enc.typ(ABIContractType.ADDRESS)
     89         enc.typ(ABIContractType.ADDRESS)
     90         enc.address(holder_address)
     91         enc.address(operator_address)
     92         data = add_0x(enc.get())
     93         tx = self.template(sender_address, contract_address)
     94         tx = self.set_code(tx, data)
     95         o['params'].append(self.normalize(tx))
     96         o['params'].append('latest')
     97         o = j.finalize(o)
     98         return o
     99 
    100 
    101     def is_operator(self, contract_address, token_id, operator_address, sender_address=ZERO_ADDRESS):
    102         return self.is_approved_for_all(contract_address, token_id, operator_address, sender_address=sender_address)
    103 
    104 
    105     def get_approved(self, contract_address, token_id, sender_address=ZERO_ADDRESS, id_generator=None):
    106         j = JSONRPCRequest(id_generator)
    107         o = j.template()
    108         o['method'] = 'eth_call'
    109         enc = ABIContractEncoder()
    110         enc.method('getApproved')
    111         enc.typ(ABIContractType.UINT256)
    112         enc.uint256(token_id)
    113         data = add_0x(enc.get())
    114         tx = self.template(sender_address, contract_address)
    115         tx = self.set_code(tx, data)
    116         o['params'].append(self.normalize(tx))
    117         o['params'].append('latest')
    118         o = j.finalize(o)
    119         return o
    120 
    121 
    122 
    123     def token_of_owner_by_index(self, contract_address, holder_address, idx, sender_address=ZERO_ADDRESS, id_generator=None):
    124         j = JSONRPCRequest(id_generator)
    125         o = j.template()
    126         o['method'] = 'eth_call'
    127         enc = ABIContractEncoder()
    128         enc.method('tokenOfOwnerByIndex')
    129         enc.typ(ABIContractType.ADDRESS)
    130         enc.typ(ABIContractType.UINT256)
    131         enc.address(holder_address)
    132         enc.uint256(idx)
    133         data = add_0x(enc.get())
    134         tx = self.template(sender_address, contract_address)
    135         tx = self.set_code(tx, data)
    136         o['params'].append(self.normalize(tx))
    137         o['params'].append('latest')
    138         o = j.finalize(o)
    139         return o
    140 
    141 
    142     def token_uri(self, contract_address, token_id, sender_address=ZERO_ADDRESS, id_generator=None):
    143         j = JSONRPCRequest(id_generator)
    144         o = j.template()
    145         o['method'] = 'eth_call'
    146         enc = ABIContractEncoder()
    147         enc.method('tokenURI')
    148         enc.typ(ABIContractType.UINT256)
    149         enc.uint256(token_id)
    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         o['params'].append('latest')
    155         o = j.finalize(o)
    156         return o
    157 
    158 
    159     @classmethod
    160     def parse_owner_of(self, v):
    161         return abi_decode_single(ABIContractType.ADDRESS, v)
    162 
    163 
    164     @classmethod
    165     def parse_token_by_index(self, v):
    166         return abi_decode_single(ABIContractType.UINT256, v)
    167 
    168 
    169     @classmethod
    170     def parse_token_of_owner_by_index(self, v):
    171         return abi_decode_single(ABIContractType.UINT256, v)
    172 
    173 
    174     @classmethod
    175     def parse_total_supply(self, v):
    176         return abi_decode_single(ABIContractType.UINT256, v)
    177 
    178 
    179     @classmethod
    180     def parse_is_approved_for_all(self, v):
    181         return abi_decode_single(ABIContractType.BOOLEAN, v)
    182 
    183 
    184     @classmethod
    185     def parse_is_operator(self, v):
    186         return self.parse_is_approved_for_all(v)
    187 
    188 
    189     @classmethod
    190     def parse_get_approved(self, v):
    191         return abi_decode_single(ABIContractType.ADDRESS, v)
    192 
    193 
    194     @classmethod
    195     def parse_token_uri(self, v):
    196         return abi_decode_single(ABIContractType.STRING, v)