eth-erc721

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

commit 921d493b987145f8802f52a0cc21c3a41ae07b02
parent 8c49343202050d2411d912760d778dcdbf530aa9
Author: nolash <dev@holbrook.no>
Date:   Sat,  8 May 2021 07:46:17 +0200

Add approve test

Diffstat:
Mpython/eth_devbadge/token.py | 42++++++++++++++++++------------------------
Mpython/tests/test_app.py | 42++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 24 deletions(-)

diff --git a/python/eth_devbadge/token.py b/python/eth_devbadge/token.py @@ -17,6 +17,7 @@ from hexathon import ( add_0x, strip_0x, ) +from eth_erc20 import ERC20 # local imports #from .interface import BadgeToken @@ -25,7 +26,7 @@ moddir = os.path.dirname(__file__) datadir = os.path.join(moddir, 'data') -class BadgeToken(TxFactory): +class BadgeToken(ERC20): __abi = None __bytecode = None @@ -79,22 +80,6 @@ class BadgeToken(TxFactory): return tx - def transfer_from(self, contract_address, sender_address, holder_address, beneficiary_address, token_id, tx_format=TxFormat.JSONRPC): - enc = ABIContractEncoder() - enc.method('transferFrom') - enc.typ(ABIContractType.ADDRESS) - enc.typ(ABIContractType.ADDRESS) - enc.typ(ABIContractType.UINT256) - enc.address(holder_address) - enc.address(beneficiary_address) - enc.uint256(token_id) - data = enc.get() - tx = self.template(sender_address, contract_address, use_nonce=True) - tx = self.set_code(tx, data) - tx = self.finalize(tx, tx_format) - return tx - - def set_approve_for_all(self, contract_address, sender_address, operator_address, flag, tx_format=TxFormat.JSONRPC): enc = ABIContractEncoder() enc.method('setApprovalForAll') @@ -168,15 +153,13 @@ class BadgeToken(TxFactory): return self.is_approved_for_all(contract_address, token_id, operator_address, sender_address=sender_address) - def token_of_owner_by_index(self, contract_address, holder_address, idx, sender_address=ZERO_ADDRESS): + def get_approved(self, contract_address, token_id, sender_address=ZERO_ADDRESS): o = jsonrpc_template() o['method'] = 'eth_call' enc = ABIContractEncoder() - enc.method('tokenOfOwnerByIndex') - enc.typ(ABIContractType.ADDRESS) + enc.method('getApproved') enc.typ(ABIContractType.UINT256) - enc.address(holder_address) - enc.uint256(idx) + enc.uint256(token_id) data = add_0x(enc.get()) tx = self.template(sender_address, contract_address) tx = self.set_code(tx, data) @@ -185,11 +168,15 @@ class BadgeToken(TxFactory): return o - def total_supply(self, contract_address, sender_address=ZERO_ADDRESS): + def token_of_owner_by_index(self, contract_address, holder_address, idx, sender_address=ZERO_ADDRESS): o = jsonrpc_template() o['method'] = 'eth_call' enc = ABIContractEncoder() - enc.method('totalSupply') + enc.method('tokenOfOwnerByIndex') + enc.typ(ABIContractType.ADDRESS) + enc.typ(ABIContractType.UINT256) + enc.address(holder_address) + enc.uint256(idx) data = add_0x(enc.get()) tx = self.template(sender_address, contract_address) tx = self.set_code(tx, data) @@ -226,3 +213,10 @@ class BadgeToken(TxFactory): @classmethod def parse_is_operator(self, v): return self.parse_is_approved_for_all(v) + + + @classmethod + def parse_get_approved(self, v): + return abi_decode_single(ABIContractType.ADDRESS, v) + + diff --git a/python/tests/test_app.py b/python/tests/test_app.py @@ -19,6 +19,7 @@ from chainlib.eth.contract import ( ABIContractType, ) from chainlib.error import JSONRPCException +from chainlib.eth.constant import ZERO_ADDRESS from hexathon import ( add_0x, strip_0x, @@ -94,6 +95,47 @@ class Test(EthTesterCase): r = self.rpc.do(o) self.assertEqual(token_bytes.hex(), strip_0x(r)) + + def test_approve(self): + token_bytes = b'\xee' * 32 + token_id = int.from_bytes(token_bytes, byteorder='big') + c = self._mint(self.accounts[1], token_id) + + nonce_oracle = RPCNonceOracle(self.accounts[1], self.rpc) + c = BadgeToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + (tx_hash_hex, o) = c.approve(self.address, self.accounts[1], self.accounts[2], token_id) + r = self.rpc.do(o) + + o = receipt(tx_hash_hex) + r = self.conn.do(o) + self.assertEqual(r['status'], 1) + + o = c.get_approved(self.address, token_id, sender_address=self.accounts[0]) + r = self.rpc.do(o) + approved_address = c.parse_get_approved(r) + self.assertEqual(approved_address, self.accounts[2]) + + nonce_oracle = RPCNonceOracle(self.accounts[2], self.rpc) + c = BadgeToken(self.chain_spec, signer=self.signer, nonce_oracle=nonce_oracle) + (tx_hash_hex, o) = c.transfer_from(self.address, self.accounts[2], self.accounts[1], self.accounts[3], token_id) + r = self.rpc.do(o) + + o = receipt(tx_hash_hex) + r = self.conn.do(o) + self.assertEqual(r['status'], 1) + + o = c.owner_of(self.address, token_id, sender_address=self.accounts[0]) + r = self.rpc.do(o) + owner_address = c.parse_owner_of(r) + self.assertEqual(owner_address, self.accounts[3]) + + o = c.get_approved(self.address, token_id, sender_address=self.accounts[0]) + r = self.rpc.do(o) + approved_address = c.parse_get_approved(r) + self.assertEqual(approved_address, ZERO_ADDRESS) + + + def test_operator(self): token_bytes = b'\xee' * 32