From 391a4d057bf54ea63d2e3d97a76d02f43ff2fdc3 Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 17 Dec 2024 16:52:46 -0800 Subject: [PATCH] add checking --- cdp/smart_contract.py | 22 +++++++++------ tests/factories/smart_contract_factory.py | 20 +++++++++++++ tests/test_smart_contract.py | 34 +++++++++++++++++++++++ 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/cdp/smart_contract.py b/cdp/smart_contract.py index dd5379c..b316f5c 100644 --- a/cdp/smart_contract.py +++ b/cdp/smart_contract.py @@ -31,7 +31,7 @@ class Type(Enum): ERC20 = "erc20" ERC721 = "erc721" ERC1155 = "erc1155" - Custom = "custom" + CUSTOM = "custom" def __str__(self) -> str: """Return a string representation of the Type.""" @@ -124,8 +124,6 @@ def wallet_id(self) -> str | None: The wallet ID. """ - if self._model.is_external: - return None return self._model.wallet_id @property @@ -156,8 +154,6 @@ def deployer_address(self) -> str | None: The deployer address. """ - if self._model.is_external: - return None return self._model.deployer_address @property @@ -194,8 +190,9 @@ def options(self) -> TokenContractOptions | NFTContractOptions | MultiTokenContr ValueError: If the smart contract type is unknown or if options are not set. """ - if self._model.is_external: - return None + if self.is_external: + raise ValueError("SmartContract options cannot be returned for external SmartContract") + if self._model.options is None or self._model.options.actual_instance is None: raise ValueError("Smart contract options are not set") @@ -227,7 +224,7 @@ def transaction(self) -> Transaction | None: Transaction: The transaction. """ - if self._model.is_external: + if self.is_external: return None if self._transaction is None and self._model.transaction is not None: self._update_transaction(self._model) @@ -246,6 +243,8 @@ def sign(self, key: LocalAccount) -> "SmartContract": ValueError: If the key is not a LocalAccount. """ + if self.is_external: + raise ValueError("Cannot sign an external SmartContract") if not isinstance(key, LocalAccount): raise ValueError("key must be a LocalAccount") @@ -262,6 +261,9 @@ def broadcast(self) -> "SmartContract": ValueError: If the smart contract deployment is not signed. """ + if self.is_external: + raise ValueError("Cannot broadcast an external SmartContract") + if not self.transaction.signed: raise ValueError("Cannot broadcast unsigned SmartContract deployment") @@ -285,6 +287,8 @@ def reload(self) -> "SmartContract": The updated SmartContract object. """ + if self.is_external: + raise ValueError("Cannot reload an external SmartContract") model = Cdp.api_clients.smart_contracts.get_smart_contract( wallet_id=self.wallet_id, address_id=self.deployer_address, @@ -308,6 +312,8 @@ def wait(self, interval_seconds: float = 0.2, timeout_seconds: float = 10) -> "S TimeoutError: If the smart contract deployment times out. """ + if self.is_external: + raise ValueError("Cannot wait for an external SmartContract") start_time = time.time() while self.transaction is not None and not self.transaction.terminal_state: self.reload() diff --git a/tests/factories/smart_contract_factory.py b/tests/factories/smart_contract_factory.py index b397cbf..8a8aa1f 100644 --- a/tests/factories/smart_contract_factory.py +++ b/tests/factories/smart_contract_factory.py @@ -30,6 +30,26 @@ def _create_smart_contract_model(status="complete"): return _create_smart_contract_model +@pytest.fixture +def external_smart_contract_factory(transaction_model_factory): + """Create and return a factory for creating SmartContractModel fixtures.""" + + def _create_smart_contract_model(status="complete"): + token_options = TokenContractOptions(name="TestToken", symbol="TT", total_supply="1000000") + smart_contract_options = SmartContractOptions(actual_instance=token_options) + + return SmartContract(SmartContractModel( + smart_contract_id="test-contract-id", + network_id="base-sepolia", + contract_address="0xcontractaddress", + contract_name="TestContract", + type="custom", + abi='{"abi":"data"}', + is_external=True, + )) + + return _create_smart_contract_model + @pytest.fixture def smart_contract_factory(smart_contract_model_factory): diff --git a/tests/test_smart_contract.py b/tests/test_smart_contract.py index a50ceae..73a5c15 100644 --- a/tests/test_smart_contract.py +++ b/tests/test_smart_contract.py @@ -37,6 +37,20 @@ def test_smart_contract_properties(smart_contract_factory): ) assert smart_contract.transaction.transaction_hash == "0xtransactionhash" +def test_external_smart_contract_properties(external_smart_contract_factory): + """Test the properties of a SmartContract object.""" + smart_contract = external_smart_contract_factory() + assert smart_contract.smart_contract_id == "test-contract-id" + assert smart_contract.network_id == "base-sepolia" + assert smart_contract.contract_address == "0xcontractaddress" + assert smart_contract.type.value == SmartContract.Type.CUSTOM.value + assert smart_contract.abi == {"abi": "data"} + + assert not smart_contract.wallet_id + assert not smart_contract.deployer_address + assert not smart_contract.transaction + with pytest.raises(ValueError, match="SmartContract options cannot be returned for external SmartContract"): + smart_contract.options @patch("cdp.Cdp.api_clients") def test_create_smart_contract(mock_api_clients, smart_contract_factory): @@ -86,6 +100,11 @@ def test_broadcast_unsigned_smart_contract(smart_contract_factory): with pytest.raises(ValueError, match="Cannot broadcast unsigned SmartContract deployment"): smart_contract.broadcast() +def test_broadcast_external_smart_contract(external_smart_contract_factory): + """Test the broadcasting of an external SmartContract object.""" + smart_contract = external_smart_contract_factory() + with pytest.raises(ValueError, match="Cannot broadcast an external SmartContract"): + smart_contract.broadcast() @patch("cdp.Cdp.api_clients") def test_reload_smart_contract(mock_api_clients, smart_contract_factory): @@ -105,6 +124,11 @@ def test_reload_smart_contract(mock_api_clients, smart_contract_factory): ) assert smart_contract.transaction.status.value == "complete" +def test_reload_external_smart_contract(external_smart_contract_factory): + """Test the reloading of an external SmartContract object.""" + smart_contract = external_smart_contract_factory() + with pytest.raises(ValueError, match="Cannot reload an external SmartContract"): + smart_contract.reload() @patch("cdp.Cdp.api_clients") @patch("cdp.smart_contract.time.sleep") @@ -131,6 +155,11 @@ def test_wait_for_smart_contract(mock_time, mock_sleep, mock_api_clients, smart_ mock_sleep.assert_has_calls([call(0.2)] * 2) assert mock_time.call_count == 3 +def test_wait_external_smart_contract(external_smart_contract_factory): + """Test the waiting of an external SmartContract object.""" + smart_contract = external_smart_contract_factory() + with pytest.raises(ValueError, match="Cannot wait for an external SmartContract"): + smart_contract.wait() @patch("cdp.Cdp.api_clients") @patch("cdp.smart_contract.time.sleep") @@ -159,6 +188,11 @@ def test_sign_smart_contract_invalid_key(smart_contract_factory): with pytest.raises(ValueError, match="key must be a LocalAccount"): smart_contract.sign("invalid_key") +def test_sign_external_smart_contract(external_smart_contract_factory): + """Test the signing of an external SmartContract object.""" + smart_contract = external_smart_contract_factory() + with pytest.raises(ValueError, match="Cannot sign an external SmartContract"): + smart_contract.sign('key') def test_smart_contract_str_representation(smart_contract_factory): """Test the string representation of a SmartContract object."""