eth-erc721

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

commit 8c49343202050d2411d912760d778dcdbf530aa9
parent d5174a7acaad0a395bbbd48b4e8ab29176eed2ee
Author: nolash <dev@holbrook.no>
Date:   Sat,  8 May 2021 07:34:58 +0200

Implement operator

Diffstat:
Mpython/eth_devbadge/token.py | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Mpython/tests/test_app.py | 53+++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/python/eth_devbadge/token.py b/python/eth_devbadge/token.py @@ -95,6 +95,28 @@ class BadgeToken(TxFactory): return tx + def set_approve_for_all(self, contract_address, sender_address, operator_address, flag, tx_format=TxFormat.JSONRPC): + enc = ABIContractEncoder() + enc.method('setApprovalForAll') + enc.typ(ABIContractType.ADDRESS) + enc.typ(ABIContractType.BOOLEAN) + enc.address(operator_address) + enc.uint256(int(flag)) + 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_operator(self, contract_address, sender_address, operator_address, tx_format=TxFormat.JSONRPC): + return self.set_approve_for_all(contract_address, sender_address, operator_address, True, tx_format=tx_format) + + + def remove_operator(self, contract_address, sender_address, operator_address, tx_format=TxFormat.JSONRPC): + return self.set_approve_for_all(contract_address, sender_address, operator_address, False, tx_format=tx_format) + + def token_by_index(self, contract_address, idx, sender_address=ZERO_ADDRESS): o = jsonrpc_template() o['method'] = 'eth_call' @@ -125,6 +147,27 @@ class BadgeToken(TxFactory): return o + def is_approved_for_all(self, contract_address, holder_address, operator_address, sender_address=ZERO_ADDRESS): + o = jsonrpc_template() + o['method'] = 'eth_call' + enc = ABIContractEncoder() + enc.method('isApprovedForAll') + enc.typ(ABIContractType.ADDRESS) + enc.typ(ABIContractType.ADDRESS) + enc.address(holder_address) + enc.address(operator_address) + data = add_0x(enc.get()) + tx = self.template(sender_address, contract_address) + tx = self.set_code(tx, data) + o['params'].append(self.normalize(tx)) + o['params'].append('latest') + return o + + + def is_operator(self, contract_address, token_id, operator_address, sender_address=ZERO_ADDRESS): + 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): o = jsonrpc_template() o['method'] = 'eth_call' @@ -175,3 +218,11 @@ class BadgeToken(TxFactory): return abi_decode_single(ABIContractType.UINT256, v) + @classmethod + def parse_is_approved_for_all(self, v): + return abi_decode_single(ABIContractType.BOOLEAN, v) + + + @classmethod + def parse_is_operator(self, v): + return self.parse_is_approved_for_all(v) diff --git a/python/tests/test_app.py b/python/tests/test_app.py @@ -94,6 +94,55 @@ class Test(EthTesterCase): r = self.rpc.do(o) self.assertEqual(token_bytes.hex(), strip_0x(r)) + + def test_operator(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.set_operator(self.address, self.accounts[1], self.accounts[2]) + r = self.rpc.do(o) + + o = receipt(tx_hash_hex) + r = self.conn.do(o) + self.assertEqual(r['status'], 1) + + o = c.is_operator(self.address, self.accounts[1], self.accounts[2], sender_address=self.accounts[0]) + r = self.rpc.do(o) + isop = c.parse_is_operator(r) + self.assertTrue(isop) + + (tx_hash_hex, o) = c.remove_operator(self.address, self.accounts[1], self.accounts[2]) + r = self.rpc.do(o) + + o = receipt(tx_hash_hex) + r = self.conn.do(o) + self.assertEqual(r['status'], 1) + + o = c.is_operator(self.address, self.accounts[1], self.accounts[2], sender_address=self.accounts[0]) + r = self.rpc.do(o) + isop = c.parse_is_operator(r) + self.assertFalse(isop) + + (tx_hash_hex, o) = c.set_operator(self.address, self.accounts[1], self.accounts[2]) + r = self.rpc.do(o) + + 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]) + def test_transfer(self): token_bytes = b'\xee' * 32 @@ -113,10 +162,10 @@ class Test(EthTesterCase): with self.assertRaises(JSONRPCException): r = self.rpc.do(o) - o = c.token_of_owner_by_index(self.address, self.accounts[2], 0, sender_address=self.accounts[0]) r = self.rpc.do(o) self.assertEqual(token_bytes.hex(), strip_0x(r)) - + + if __name__ == '__main__': unittest.main()