From d48dad0ed5c49c443c35a7771d51192fe5bf9c07 Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 10 Dec 2024 01:40:58 -0800 Subject: [PATCH 1/8] feat: Support Register/List/Update Smart Contract --- cdp/client/__init__.py | 4 +- cdp/client/api/addresses_api.py | 15 + cdp/client/api/assets_api.py | 2 + cdp/client/api/balance_history_api.py | 2 + cdp/client/api/contract_events_api.py | 2 + cdp/client/api/contract_invocations_api.py | 6 + cdp/client/api/external_addresses_api.py | 8 + cdp/client/api/fund_api.py | 6 + cdp/client/api/mpc_wallet_stake_api.py | 4 + cdp/client/api/networks_api.py | 2 + cdp/client/api/onchain_identity_api.py | 2 + cdp/client/api/reputation_api.py | 278 +------------ cdp/client/api/server_signers_api.py | 8 + cdp/client/api/smart_contracts_api.py | 388 ++++++++++++++++-- cdp/client/api/stake_api.py | 14 + cdp/client/api/trades_api.py | 6 + cdp/client/api/transaction_history_api.py | 2 + cdp/client/api/transfers_api.py | 6 + cdp/client/api/wallets_api.py | 9 + cdp/client/api/webhooks_api.py | 10 + cdp/client/configuration.py | 38 ++ cdp/client/models/__init__.py | 4 +- cdp/client/models/address_reputation.py | 6 +- .../models/register_smart_contract_request.py | 90 ++++ cdp/client/models/smart_contract.py | 20 +- cdp/client/models/transfer.py | 16 +- .../models/update_smart_contract_request.py | 90 ++++ cdp/smart_contract.py | 124 ++++++ cdp/wallet_address.py | 4 +- tests/factories/smart_contract_factory.py | 3 +- tests/test_smart_contract.py | 79 ++++ tests/test_wallet_address.py | 12 +- 32 files changed, 911 insertions(+), 349 deletions(-) create mode 100644 cdp/client/models/register_smart_contract_request.py create mode 100644 cdp/client/models/update_smart_contract_request.py diff --git a/cdp/client/__init__.py b/cdp/client/__init__.py index 216b8c1..68ff0a9 100644 --- a/cdp/client/__init__.py +++ b/cdp/client/__init__.py @@ -50,14 +50,12 @@ from cdp.client.exceptions import ApiException # import models into sdk package -from cdp.client.models.abi import ABI from cdp.client.models.address import Address from cdp.client.models.address_balance_list import AddressBalanceList from cdp.client.models.address_historical_balance_list import AddressHistoricalBalanceList from cdp.client.models.address_list import AddressList from cdp.client.models.address_reputation import AddressReputation from cdp.client.models.address_reputation_metadata import AddressReputationMetadata -from cdp.client.models.address_risk import AddressRisk from cdp.client.models.address_transaction_list import AddressTransactionList from cdp.client.models.asset import Asset from cdp.client.models.balance import Balance @@ -116,6 +114,7 @@ from cdp.client.models.payload_signature import PayloadSignature from cdp.client.models.payload_signature_list import PayloadSignatureList from cdp.client.models.read_contract_request import ReadContractRequest +from cdp.client.models.register_smart_contract_request import RegisterSmartContractRequest from cdp.client.models.seed_creation_event import SeedCreationEvent from cdp.client.models.seed_creation_event_result import SeedCreationEventResult from cdp.client.models.server_signer import ServerSigner @@ -150,6 +149,7 @@ from cdp.client.models.transaction_type import TransactionType from cdp.client.models.transfer import Transfer from cdp.client.models.transfer_list import TransferList +from cdp.client.models.update_smart_contract_request import UpdateSmartContractRequest from cdp.client.models.update_webhook_request import UpdateWebhookRequest from cdp.client.models.user import User from cdp.client.models.validator import Validator diff --git a/cdp/client/api/addresses_api.py b/cdp/client/api/addresses_api.py index 4ec0209..fb0dd2e 100644 --- a/cdp/client/api/addresses_api.py +++ b/cdp/client/api/addresses_api.py @@ -315,6 +315,7 @@ def _create_address_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -618,6 +619,7 @@ def _create_payload_signature_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -893,6 +895,8 @@ def _get_address_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1183,6 +1187,8 @@ def _get_address_balance_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1473,6 +1479,8 @@ def _get_payload_signature_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1765,6 +1773,8 @@ def _list_address_balances_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -2059,6 +2069,8 @@ def _list_addresses_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -2368,6 +2380,8 @@ def _list_payload_signatures_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -2663,6 +2677,7 @@ def _request_faucet_funds_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/assets_api.py b/cdp/client/api/assets_api.py index 8d82e45..4729160 100644 --- a/cdp/client/api/assets_api.py +++ b/cdp/client/api/assets_api.py @@ -293,6 +293,8 @@ def _get_asset_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/balance_history_api.py b/cdp/client/api/balance_history_api.py index 9bd47f5..3e9abf4 100644 --- a/cdp/client/api/balance_history_api.py +++ b/cdp/client/api/balance_history_api.py @@ -343,6 +343,8 @@ def _list_address_historical_balance_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/contract_events_api.py b/cdp/client/api/contract_events_api.py index c425a7b..c8cc88c 100644 --- a/cdp/client/api/contract_events_api.py +++ b/cdp/client/api/contract_events_api.py @@ -396,6 +396,8 @@ def _list_contract_events_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/contract_invocations_api.py b/cdp/client/api/contract_invocations_api.py index 8082d7b..083b34f 100644 --- a/cdp/client/api/contract_invocations_api.py +++ b/cdp/client/api/contract_invocations_api.py @@ -340,6 +340,7 @@ def _broadcast_contract_invocation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -643,6 +644,7 @@ def _create_contract_invocation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -933,6 +935,8 @@ def _get_contract_invocation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1242,6 +1246,8 @@ def _list_contract_invocations_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/external_addresses_api.py b/cdp/client/api/external_addresses_api.py index 6fd201f..857820f 100644 --- a/cdp/client/api/external_addresses_api.py +++ b/cdp/client/api/external_addresses_api.py @@ -311,6 +311,8 @@ def _get_external_address_balance_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -601,6 +603,8 @@ def _get_faucet_transaction_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -893,6 +897,8 @@ def _list_external_address_balances_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1202,6 +1208,8 @@ def _request_external_faucet_funds_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/fund_api.py b/cdp/client/api/fund_api.py index 9dd56c1..e4ed67e 100644 --- a/cdp/client/api/fund_api.py +++ b/cdp/client/api/fund_api.py @@ -326,6 +326,7 @@ def _create_fund_operation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -629,6 +630,7 @@ def _create_fund_quote_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -919,6 +921,8 @@ def _get_fund_operation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1228,6 +1232,8 @@ def _list_fund_operations_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/mpc_wallet_stake_api.py b/cdp/client/api/mpc_wallet_stake_api.py index 1d309e2..544e5d3 100644 --- a/cdp/client/api/mpc_wallet_stake_api.py +++ b/cdp/client/api/mpc_wallet_stake_api.py @@ -338,6 +338,7 @@ def _broadcast_staking_operation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -641,6 +642,7 @@ def _create_staking_operation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -931,6 +933,8 @@ def _get_staking_operation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/networks_api.py b/cdp/client/api/networks_api.py index de7dd00..0c60658 100644 --- a/cdp/client/api/networks_api.py +++ b/cdp/client/api/networks_api.py @@ -278,6 +278,8 @@ def _get_network_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/onchain_identity_api.py b/cdp/client/api/onchain_identity_api.py index e09fdf8..8ab19b1 100644 --- a/cdp/client/api/onchain_identity_api.py +++ b/cdp/client/api/onchain_identity_api.py @@ -346,6 +346,8 @@ def _resolve_identity_by_address_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/reputation_api.py b/cdp/client/api/reputation_api.py index 5d77525..7755e6c 100644 --- a/cdp/client/api/reputation_api.py +++ b/cdp/client/api/reputation_api.py @@ -19,7 +19,6 @@ from pydantic import Field, StrictStr from typing_extensions import Annotated from cdp.client.models.address_reputation import AddressReputation -from cdp.client.models.address_risk import AddressRisk from cdp.client.api_client import ApiClient, RequestSerialized from cdp.client.api_response import ApiResponse @@ -294,6 +293,8 @@ def _get_address_reputation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -312,278 +313,3 @@ def _get_address_reputation_serialize( ) - - - @validate_call - def get_address_risk( - self, - network_id: Annotated[StrictStr, Field(description="The ID of the blockchain network.")], - address_id: Annotated[StrictStr, Field(description="The ID of the address to fetch the risk for.")], - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> AddressRisk: - """Get the risk of an address - - Get the risk of an address - - :param network_id: The ID of the blockchain network. (required) - :type network_id: str - :param address_id: The ID of the address to fetch the risk for. (required) - :type address_id: str - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._get_address_risk_serialize( - network_id=network_id, - address_id=address_id, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "AddressRisk", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - response_data.read() - return self.api_client.response_deserialize( - response_data=response_data, - response_types_map=_response_types_map, - ).data - - - @validate_call - def get_address_risk_with_http_info( - self, - network_id: Annotated[StrictStr, Field(description="The ID of the blockchain network.")], - address_id: Annotated[StrictStr, Field(description="The ID of the address to fetch the risk for.")], - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[AddressRisk]: - """Get the risk of an address - - Get the risk of an address - - :param network_id: The ID of the blockchain network. (required) - :type network_id: str - :param address_id: The ID of the address to fetch the risk for. (required) - :type address_id: str - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._get_address_risk_serialize( - network_id=network_id, - address_id=address_id, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "AddressRisk", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - response_data.read() - return self.api_client.response_deserialize( - response_data=response_data, - response_types_map=_response_types_map, - ) - - - @validate_call - def get_address_risk_without_preload_content( - self, - network_id: Annotated[StrictStr, Field(description="The ID of the blockchain network.")], - address_id: Annotated[StrictStr, Field(description="The ID of the address to fetch the risk for.")], - _request_timeout: Union[ - None, - Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] - ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = None, - _content_type: Optional[StrictStr] = None, - _headers: Optional[Dict[StrictStr, Any]] = None, - _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> RESTResponseType: - """Get the risk of an address - - Get the risk of an address - - :param network_id: The ID of the blockchain network. (required) - :type network_id: str - :param address_id: The ID of the address to fetch the risk for. (required) - :type address_id: str - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :type _request_timeout: int, tuple(int, int), optional - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the - authentication in the spec for a single request. - :type _request_auth: dict, optional - :param _content_type: force content-type for the request. - :type _content_type: str, Optional - :param _headers: set to override the headers for a single - request; this effectively ignores the headers - in the spec for a single request. - :type _headers: dict, optional - :param _host_index: set to override the host_index for a single - request; this effectively ignores the host_index - in the spec for a single request. - :type _host_index: int, optional - :return: Returns the result object. - """ # noqa: E501 - - _param = self._get_address_risk_serialize( - network_id=network_id, - address_id=address_id, - _request_auth=_request_auth, - _content_type=_content_type, - _headers=_headers, - _host_index=_host_index - ) - - _response_types_map: Dict[str, Optional[str]] = { - '200': "AddressRisk", - } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response - - - def _get_address_risk_serialize( - self, - network_id, - address_id, - _request_auth, - _content_type, - _headers, - _host_index, - ) -> RequestSerialized: - - _host = None - - _collection_formats: Dict[str, str] = { - } - - _path_params: Dict[str, str] = {} - _query_params: List[Tuple[str, str]] = [] - _header_params: Dict[str, Optional[str]] = _headers or {} - _form_params: List[Tuple[str, str]] = [] - _files: Dict[ - str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] - ] = {} - _body_params: Optional[bytes] = None - - # process the path parameters - if network_id is not None: - _path_params['network_id'] = network_id - if address_id is not None: - _path_params['address_id'] = address_id - # process the query parameters - # process the header parameters - # process the form parameters - # process the body parameter - - - # set the HTTP header `Accept` - if 'Accept' not in _header_params: - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) - - - # authentication setting - _auth_settings: List[str] = [ - ] - - return self.api_client.param_serialize( - method='GET', - resource_path='/v1/networks/{network_id}/addresses/{address_id}/risk', - path_params=_path_params, - query_params=_query_params, - header_params=_header_params, - body=_body_params, - post_params=_form_params, - files=_files, - auth_settings=_auth_settings, - collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth - ) - - diff --git a/cdp/client/api/server_signers_api.py b/cdp/client/api/server_signers_api.py index 84e3e82..1d4fb4d 100644 --- a/cdp/client/api/server_signers_api.py +++ b/cdp/client/api/server_signers_api.py @@ -297,6 +297,7 @@ def _create_server_signer_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -557,6 +558,8 @@ def _get_server_signer_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -854,6 +857,7 @@ def _list_server_signer_events_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -1133,6 +1137,8 @@ def _list_server_signers_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1421,6 +1427,7 @@ def _submit_server_signer_seed_event_result_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -1709,6 +1716,7 @@ def _submit_server_signer_signature_event_result_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/smart_contracts_api.py b/cdp/client/api/smart_contracts_api.py index ab3a59e..3fe3ac2 100644 --- a/cdp/client/api/smart_contracts_api.py +++ b/cdp/client/api/smart_contracts_api.py @@ -19,13 +19,14 @@ from pydantic import Field, StrictStr from typing import Optional from typing_extensions import Annotated -from cdp.client.models.abi import ABI from cdp.client.models.create_smart_contract_request import CreateSmartContractRequest from cdp.client.models.deploy_smart_contract_request import DeploySmartContractRequest from cdp.client.models.read_contract_request import ReadContractRequest +from cdp.client.models.register_smart_contract_request import RegisterSmartContractRequest from cdp.client.models.smart_contract import SmartContract from cdp.client.models.smart_contract_list import SmartContractList from cdp.client.models.solidity_value import SolidityValue +from cdp.client.models.update_smart_contract_request import UpdateSmartContractRequest from cdp.client.api_client import ApiClient, RequestSerialized from cdp.client.api_response import ApiResponse @@ -328,6 +329,7 @@ def _create_smart_contract_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -646,6 +648,7 @@ def _deploy_smart_contract_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -936,6 +939,8 @@ def _get_smart_contract_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1198,6 +1203,8 @@ def _list_smart_contracts_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1501,6 +1508,8 @@ def _read_contract_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1524,9 +1533,9 @@ def _read_contract_serialize( @validate_call def register_smart_contract( self, - contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], network_id: Annotated[StrictStr, Field(description="The ID of the network to fetch.")], - abi: ABI, + contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], + register_smart_contract_request: Optional[RegisterSmartContractRequest] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1539,17 +1548,17 @@ def register_smart_contract( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> None: + ) -> SmartContract: """Register a smart contract Register a smart contract - :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) - :type contract_address: str :param network_id: The ID of the network to fetch. (required) :type network_id: str - :param abi: (required) - :type abi: ABI + :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) + :type contract_address: str + :param register_smart_contract_request: + :type register_smart_contract_request: RegisterSmartContractRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -1573,9 +1582,9 @@ def register_smart_contract( """ # noqa: E501 _param = self._register_smart_contract_serialize( - contract_address=contract_address, network_id=network_id, - abi=abi, + contract_address=contract_address, + register_smart_contract_request=register_smart_contract_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1583,7 +1592,7 @@ def register_smart_contract( ) _response_types_map: Dict[str, Optional[str]] = { - '200': None, + '200': "SmartContract", } response_data = self.api_client.call_api( *_param, @@ -1599,9 +1608,9 @@ def register_smart_contract( @validate_call def register_smart_contract_with_http_info( self, - contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], network_id: Annotated[StrictStr, Field(description="The ID of the network to fetch.")], - abi: ABI, + contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], + register_smart_contract_request: Optional[RegisterSmartContractRequest] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1614,17 +1623,17 @@ def register_smart_contract_with_http_info( _content_type: Optional[StrictStr] = None, _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, - ) -> ApiResponse[None]: + ) -> ApiResponse[SmartContract]: """Register a smart contract Register a smart contract - :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) - :type contract_address: str :param network_id: The ID of the network to fetch. (required) :type network_id: str - :param abi: (required) - :type abi: ABI + :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) + :type contract_address: str + :param register_smart_contract_request: + :type register_smart_contract_request: RegisterSmartContractRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -1648,9 +1657,9 @@ def register_smart_contract_with_http_info( """ # noqa: E501 _param = self._register_smart_contract_serialize( - contract_address=contract_address, network_id=network_id, - abi=abi, + contract_address=contract_address, + register_smart_contract_request=register_smart_contract_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1658,7 +1667,7 @@ def register_smart_contract_with_http_info( ) _response_types_map: Dict[str, Optional[str]] = { - '200': None, + '200': "SmartContract", } response_data = self.api_client.call_api( *_param, @@ -1674,9 +1683,9 @@ def register_smart_contract_with_http_info( @validate_call def register_smart_contract_without_preload_content( self, - contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], network_id: Annotated[StrictStr, Field(description="The ID of the network to fetch.")], - abi: ABI, + contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], + register_smart_contract_request: Optional[RegisterSmartContractRequest] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -1694,12 +1703,12 @@ def register_smart_contract_without_preload_content( Register a smart contract - :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) - :type contract_address: str :param network_id: The ID of the network to fetch. (required) :type network_id: str - :param abi: (required) - :type abi: ABI + :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) + :type contract_address: str + :param register_smart_contract_request: + :type register_smart_contract_request: RegisterSmartContractRequest :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of @@ -1723,9 +1732,9 @@ def register_smart_contract_without_preload_content( """ # noqa: E501 _param = self._register_smart_contract_serialize( - contract_address=contract_address, network_id=network_id, - abi=abi, + contract_address=contract_address, + register_smart_contract_request=register_smart_contract_request, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -1733,7 +1742,7 @@ def register_smart_contract_without_preload_content( ) _response_types_map: Dict[str, Optional[str]] = { - '200': None, + '200': "SmartContract", } response_data = self.api_client.call_api( *_param, @@ -1744,9 +1753,9 @@ def register_smart_contract_without_preload_content( def _register_smart_contract_serialize( self, - contract_address, network_id, - abi, + contract_address, + register_smart_contract_request, _request_auth, _content_type, _headers, @@ -1768,16 +1777,16 @@ def _register_smart_contract_serialize( _body_params: Optional[bytes] = None # process the path parameters - if contract_address is not None: - _path_params['contract_address'] = contract_address if network_id is not None: _path_params['network_id'] = network_id + if contract_address is not None: + _path_params['contract_address'] = contract_address # process the query parameters # process the header parameters # process the form parameters # process the body parameter - if abi is not None: - _body_params = abi + if register_smart_contract_request is not None: + _body_params = register_smart_contract_request # set the HTTP header `Accept` @@ -1804,6 +1813,8 @@ def _register_smart_contract_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1822,3 +1833,308 @@ def _register_smart_contract_serialize( ) + + + @validate_call + def update_smart_contract( + self, + network_id: Annotated[StrictStr, Field(description="The ID of the network to fetch.")], + contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], + update_smart_contract_request: Optional[UpdateSmartContractRequest] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> SmartContract: + """Update a smart contract + + Update a smart contract + + :param network_id: The ID of the network to fetch. (required) + :type network_id: str + :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) + :type contract_address: str + :param update_smart_contract_request: + :type update_smart_contract_request: UpdateSmartContractRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_smart_contract_serialize( + network_id=network_id, + contract_address=contract_address, + update_smart_contract_request=update_smart_contract_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SmartContract", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def update_smart_contract_with_http_info( + self, + network_id: Annotated[StrictStr, Field(description="The ID of the network to fetch.")], + contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], + update_smart_contract_request: Optional[UpdateSmartContractRequest] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[SmartContract]: + """Update a smart contract + + Update a smart contract + + :param network_id: The ID of the network to fetch. (required) + :type network_id: str + :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) + :type contract_address: str + :param update_smart_contract_request: + :type update_smart_contract_request: UpdateSmartContractRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_smart_contract_serialize( + network_id=network_id, + contract_address=contract_address, + update_smart_contract_request=update_smart_contract_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SmartContract", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def update_smart_contract_without_preload_content( + self, + network_id: Annotated[StrictStr, Field(description="The ID of the network to fetch.")], + contract_address: Annotated[StrictStr, Field(description="EVM address of the smart contract (42 characters, including '0x', in lowercase)")], + update_smart_contract_request: Optional[UpdateSmartContractRequest] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Update a smart contract + + Update a smart contract + + :param network_id: The ID of the network to fetch. (required) + :type network_id: str + :param contract_address: EVM address of the smart contract (42 characters, including '0x', in lowercase) (required) + :type contract_address: str + :param update_smart_contract_request: + :type update_smart_contract_request: UpdateSmartContractRequest + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_smart_contract_serialize( + network_id=network_id, + contract_address=contract_address, + update_smart_contract_request=update_smart_contract_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "SmartContract", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_smart_contract_serialize( + self, + network_id, + contract_address, + update_smart_contract_request, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if network_id is not None: + _path_params['network_id'] = network_id + if contract_address is not None: + _path_params['contract_address'] = contract_address + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if update_smart_contract_request is not None: + _body_params = update_smart_contract_request + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + # set the HTTP header `Content-Type` + if _content_type: + _header_params['Content-Type'] = _content_type + else: + _default_content_type = ( + self.api_client.select_header_content_type( + [ + 'application/json' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'apiKey', + 'session' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/v1/networks/{network_id}/smart_contracts/{contract_address}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/cdp/client/api/stake_api.py b/cdp/client/api/stake_api.py index f2790f3..e2b4059 100644 --- a/cdp/client/api/stake_api.py +++ b/cdp/client/api/stake_api.py @@ -302,6 +302,8 @@ def _build_staking_operation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -680,6 +682,8 @@ def _fetch_historical_staking_balances_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -987,6 +991,8 @@ def _fetch_staking_rewards_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1277,6 +1283,8 @@ def _get_external_staking_operation_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1550,6 +1558,8 @@ def _get_staking_context_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1840,6 +1850,8 @@ def _get_validator_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -2166,6 +2178,8 @@ def _list_validators_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/trades_api.py b/cdp/client/api/trades_api.py index 1e010cb..7a69a45 100644 --- a/cdp/client/api/trades_api.py +++ b/cdp/client/api/trades_api.py @@ -340,6 +340,7 @@ def _broadcast_trade_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -643,6 +644,7 @@ def _create_trade_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -933,6 +935,8 @@ def _get_trade_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1242,6 +1246,8 @@ def _list_trades_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/transaction_history_api.py b/cdp/client/api/transaction_history_api.py index 02b6ea7..6833c9f 100644 --- a/cdp/client/api/transaction_history_api.py +++ b/cdp/client/api/transaction_history_api.py @@ -328,6 +328,8 @@ def _list_address_transactions_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/transfers_api.py b/cdp/client/api/transfers_api.py index a7be92c..c4775dd 100644 --- a/cdp/client/api/transfers_api.py +++ b/cdp/client/api/transfers_api.py @@ -340,6 +340,7 @@ def _broadcast_transfer_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -643,6 +644,7 @@ def _create_transfer_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -933,6 +935,8 @@ def _get_transfer_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1242,6 +1246,8 @@ def _list_transfers_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/wallets_api.py b/cdp/client/api/wallets_api.py index 66eaa59..0a54674 100644 --- a/cdp/client/api/wallets_api.py +++ b/cdp/client/api/wallets_api.py @@ -296,6 +296,7 @@ def _create_wallet_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey' ] return self.api_client.param_serialize( @@ -556,6 +557,8 @@ def _get_wallet_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -831,6 +834,8 @@ def _get_wallet_balance_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1091,6 +1096,8 @@ def _list_wallet_balances_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1370,6 +1377,8 @@ def _list_wallets_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/api/webhooks_api.py b/cdp/client/api/webhooks_api.py index ba2844a..fcfbbf9 100644 --- a/cdp/client/api/webhooks_api.py +++ b/cdp/client/api/webhooks_api.py @@ -311,6 +311,8 @@ def _create_wallet_webhook_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -584,6 +586,8 @@ def _create_webhook_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -844,6 +848,8 @@ def _delete_webhook_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1123,6 +1129,8 @@ def _list_webhooks_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( @@ -1411,6 +1419,8 @@ def _update_webhook_serialize( # authentication setting _auth_settings: List[str] = [ + 'apiKey', + 'session' ] return self.api_client.param_serialize( diff --git a/cdp/client/configuration.py b/cdp/client/configuration.py index e995c53..8f7de86 100644 --- a/cdp/client/configuration.py +++ b/cdp/client/configuration.py @@ -59,6 +59,26 @@ class Configuration: in PEM format. :param retries: Number of retries for API requests. + :Example: + + API Key Authentication Example. + Given the following security scheme in the OpenAPI specification: + components: + securitySchemes: + cookieAuth: # name for the security scheme + type: apiKey + in: cookie + name: JSESSIONID # cookie name + + You can programmatically set the cookie: + +conf = cdp.client.Configuration( + api_key={'cookieAuth': 'abc123'} + api_key_prefix={'cookieAuth': 'JSESSIONID'} +) + + The following cookie will be added to the HTTP request: + Cookie: JSESSIONID abc123 """ _default = None @@ -373,6 +393,24 @@ def auth_settings(self): :return: The Auth Settings information dict. """ auth = {} + if 'apiKey' in self.api_key: + auth['apiKey'] = { + 'type': 'api_key', + 'in': 'header', + 'key': 'Jwt', + 'value': self.get_api_key_with_prefix( + 'apiKey', + ), + } + if 'session' in self.api_key: + auth['session'] = { + 'type': 'api_key', + 'in': 'header', + 'key': 'Jwt', + 'value': self.get_api_key_with_prefix( + 'session', + ), + } return auth def to_debug_report(self): diff --git a/cdp/client/models/__init__.py b/cdp/client/models/__init__.py index d10d6ed..9191c6a 100644 --- a/cdp/client/models/__init__.py +++ b/cdp/client/models/__init__.py @@ -14,14 +14,12 @@ # import models into model package -from cdp.client.models.abi import ABI from cdp.client.models.address import Address from cdp.client.models.address_balance_list import AddressBalanceList from cdp.client.models.address_historical_balance_list import AddressHistoricalBalanceList from cdp.client.models.address_list import AddressList from cdp.client.models.address_reputation import AddressReputation from cdp.client.models.address_reputation_metadata import AddressReputationMetadata -from cdp.client.models.address_risk import AddressRisk from cdp.client.models.address_transaction_list import AddressTransactionList from cdp.client.models.asset import Asset from cdp.client.models.balance import Balance @@ -80,6 +78,7 @@ from cdp.client.models.payload_signature import PayloadSignature from cdp.client.models.payload_signature_list import PayloadSignatureList from cdp.client.models.read_contract_request import ReadContractRequest +from cdp.client.models.register_smart_contract_request import RegisterSmartContractRequest from cdp.client.models.seed_creation_event import SeedCreationEvent from cdp.client.models.seed_creation_event_result import SeedCreationEventResult from cdp.client.models.server_signer import ServerSigner @@ -114,6 +113,7 @@ from cdp.client.models.transaction_type import TransactionType from cdp.client.models.transfer import Transfer from cdp.client.models.transfer_list import TransferList +from cdp.client.models.update_smart_contract_request import UpdateSmartContractRequest from cdp.client.models.update_webhook_request import UpdateWebhookRequest from cdp.client.models.user import User from cdp.client.models.validator import Validator diff --git a/cdp/client/models/address_reputation.py b/cdp/client/models/address_reputation.py index bbe381c..3c69e1e 100644 --- a/cdp/client/models/address_reputation.py +++ b/cdp/client/models/address_reputation.py @@ -27,9 +27,9 @@ class AddressReputation(BaseModel): """ The reputation score with metadata of a blockchain address. """ # noqa: E501 - reputation_score: StrictInt = Field(description="The reputation score of a wallet address which lie between 0 to 100.") + score: StrictInt = Field(description="The score of a wallet address, ranging from -100 to 100. A negative score indicates a bad reputation, while a positive score indicates a good reputation.") metadata: AddressReputationMetadata - __properties: ClassVar[List[str]] = ["reputation_score", "metadata"] + __properties: ClassVar[List[str]] = ["score", "metadata"] model_config = ConfigDict( populate_by_name=True, @@ -85,7 +85,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "reputation_score": obj.get("reputation_score"), + "score": obj.get("score"), "metadata": AddressReputationMetadata.from_dict(obj["metadata"]) if obj.get("metadata") is not None else None }) return _obj diff --git a/cdp/client/models/register_smart_contract_request.py b/cdp/client/models/register_smart_contract_request.py new file mode 100644 index 0000000..0095bd4 --- /dev/null +++ b/cdp/client/models/register_smart_contract_request.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + Coinbase Platform API + + This is the OpenAPI 3.0 specification for the Coinbase Platform APIs, used in conjunction with the Coinbase Platform SDKs. + + The version of the OpenAPI document: 0.0.1-alpha + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class RegisterSmartContractRequest(BaseModel): + """ + Smart Contract data to be registered + """ # noqa: E501 + abi: StrictStr = Field(description="ABI of the smart contract") + contract_name: Optional[Annotated[str, Field(strict=True, max_length=100)]] = Field(default=None, description="Name of the smart contract") + __properties: ClassVar[List[str]] = ["abi", "contract_name"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of RegisterSmartContractRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of RegisterSmartContractRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "abi": obj.get("abi"), + "contract_name": obj.get("contract_name") + }) + return _obj + + diff --git a/cdp/client/models/smart_contract.py b/cdp/client/models/smart_contract.py index 1d1a54f..3156064 100644 --- a/cdp/client/models/smart_contract.py +++ b/cdp/client/models/smart_contract.py @@ -17,8 +17,8 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr +from typing import Any, ClassVar, Dict, List, Optional from cdp.client.models.smart_contract_options import SmartContractOptions from cdp.client.models.smart_contract_type import SmartContractType from cdp.client.models.transaction import Transaction @@ -29,17 +29,18 @@ class SmartContract(BaseModel): """ Represents a smart contract on the blockchain """ # noqa: E501 - smart_contract_id: StrictStr = Field(description="The unique identifier of the smart contract") + smart_contract_id: StrictStr = Field(description="The unique identifier of the smart contract.") network_id: StrictStr = Field(description="The name of the blockchain network") - wallet_id: StrictStr = Field(description="The ID of the wallet that deployed the smart contract") + wallet_id: Optional[StrictStr] = Field(default=None, description="The ID of the wallet that deployed the smart contract. If this smart contract was deployed externally, this will be omitted.") contract_address: StrictStr = Field(description="The EVM address of the smart contract") contract_name: StrictStr = Field(description="The name of the smart contract") - deployer_address: StrictStr = Field(description="The EVM address of the account that deployed the smart contract") + deployer_address: Optional[StrictStr] = Field(default=None, description="The EVM address of the account that deployed the smart contract. If this smart contract was deployed externally, this will be omitted.") type: SmartContractType - options: SmartContractOptions + options: Optional[SmartContractOptions] = None abi: StrictStr = Field(description="The JSON-encoded ABI of the contract") - transaction: Transaction - __properties: ClassVar[List[str]] = ["smart_contract_id", "network_id", "wallet_id", "contract_address", "contract_name", "deployer_address", "type", "options", "abi", "transaction"] + transaction: Optional[Transaction] = None + is_external: StrictBool = Field(description="Whether the smart contract was deployed externally. If true, the deployer_address and transaction will be omitted.") + __properties: ClassVar[List[str]] = ["smart_contract_id", "network_id", "wallet_id", "contract_address", "contract_name", "deployer_address", "type", "options", "abi", "transaction", "is_external"] model_config = ConfigDict( populate_by_name=True, @@ -107,7 +108,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "type": obj.get("type"), "options": SmartContractOptions.from_dict(obj["options"]) if obj.get("options") is not None else None, "abi": obj.get("abi"), - "transaction": Transaction.from_dict(obj["transaction"]) if obj.get("transaction") is not None else None + "transaction": Transaction.from_dict(obj["transaction"]) if obj.get("transaction") is not None else None, + "is_external": obj.get("is_external") }) return _obj diff --git a/cdp/client/models/transfer.py b/cdp/client/models/transfer.py index 2b6fb1a..3e4a58e 100644 --- a/cdp/client/models/transfer.py +++ b/cdp/client/models/transfer.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr, field_validator +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr from typing import Any, ClassVar, Dict, List, Optional from cdp.client.models.asset import Asset from cdp.client.models.sponsored_send import SponsoredSend @@ -34,7 +34,7 @@ class Transfer(BaseModel): address_id: StrictStr = Field(description="The onchain address of the sender") destination: StrictStr = Field(description="The onchain address of the recipient") amount: StrictStr = Field(description="The amount in the atomic units of the asset") - asset_id: StrictStr = Field(description="The ID of the asset being transferred") + asset_id: StrictStr = Field(description="The ID of the asset being transferred. Use `asset.asset_id` instead.") asset: Asset transfer_id: StrictStr = Field(description="The ID of the transfer") transaction: Optional[Transaction] = None @@ -42,20 +42,10 @@ class Transfer(BaseModel): unsigned_payload: Optional[StrictStr] = Field(default=None, description="The unsigned payload of the transfer. This is the payload that needs to be signed by the sender.") signed_payload: Optional[StrictStr] = Field(default=None, description="The signed payload of the transfer. This is the payload that has been signed by the sender.") transaction_hash: Optional[StrictStr] = Field(default=None, description="The hash of the transfer transaction") - status: Optional[StrictStr] = Field(default=None, description="The status of the transfer") + status: Optional[StrictStr] = None gasless: StrictBool = Field(description="Whether the transfer uses sponsored gas") __properties: ClassVar[List[str]] = ["network_id", "wallet_id", "address_id", "destination", "amount", "asset_id", "asset", "transfer_id", "transaction", "sponsored_send", "unsigned_payload", "signed_payload", "transaction_hash", "status", "gasless"] - @field_validator('status') - def status_validate_enum(cls, value): - """Validates the enum""" - if value is None: - return value - - if value not in set(['pending', 'broadcast', 'complete', 'failed']): - raise ValueError("must be one of enum values ('pending', 'broadcast', 'complete', 'failed')") - return value - model_config = ConfigDict( populate_by_name=True, validate_assignment=True, diff --git a/cdp/client/models/update_smart_contract_request.py b/cdp/client/models/update_smart_contract_request.py new file mode 100644 index 0000000..0337fb8 --- /dev/null +++ b/cdp/client/models/update_smart_contract_request.py @@ -0,0 +1,90 @@ +# coding: utf-8 + +""" + Coinbase Platform API + + This is the OpenAPI 3.0 specification for the Coinbase Platform APIs, used in conjunction with the Coinbase Platform SDKs. + + The version of the OpenAPI document: 0.0.1-alpha + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class UpdateSmartContractRequest(BaseModel): + """ + Smart Contract data to be updated + """ # noqa: E501 + abi: Optional[StrictStr] = Field(default=None, description="ABI of the smart contract") + contract_name: Optional[Annotated[str, Field(strict=True, max_length=100)]] = Field(default=None, description="Name of the smart contract") + __properties: ClassVar[List[str]] = ["abi", "contract_name"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of UpdateSmartContractRequest from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of UpdateSmartContractRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "abi": obj.get("abi"), + "contract_name": obj.get("contract_name") + }) + return _obj + + diff --git a/cdp/smart_contract.py b/cdp/smart_contract.py index a1b919c..8242736 100644 --- a/cdp/smart_contract.py +++ b/cdp/smart_contract.py @@ -1,20 +1,24 @@ import json import time +from collections.abc import Iterator from enum import Enum from typing import Any from eth_account.signers.local import LocalAccount from cdp.cdp import Cdp +from cdp.client import SmartContractList from cdp.client.models.create_smart_contract_request import CreateSmartContractRequest from cdp.client.models.deploy_smart_contract_request import DeploySmartContractRequest from cdp.client.models.multi_token_contract_options import MultiTokenContractOptions from cdp.client.models.nft_contract_options import NFTContractOptions from cdp.client.models.read_contract_request import ReadContractRequest +from cdp.client.models.register_smart_contract_request import RegisterSmartContractRequest from cdp.client.models.smart_contract import SmartContract as SmartContractModel from cdp.client.models.smart_contract_options import SmartContractOptions from cdp.client.models.solidity_value import SolidityValue from cdp.client.models.token_contract_options import TokenContractOptions +from cdp.client.models.update_smart_contract_request import UpdateSmartContractRequest from cdp.transaction import Transaction @@ -27,6 +31,7 @@ class Type(Enum): ERC20 = "erc20" ERC721 = "erc721" ERC1155 = "erc1155" + Custom = "custom" def __str__(self) -> str: """Return a string representation of the Type.""" @@ -131,6 +136,16 @@ def contract_address(self) -> str: """ return self._model.contract_address + @property + def contract_name(self) -> str: + """Get the contract address of the smart contract. + + Returns: + The contract address. + + """ + return self._model.contract_name + @property def deployer_address(self) -> str: """Get the deployer address of the smart contract. @@ -141,6 +156,16 @@ def deployer_address(self) -> str: """ return self._model.deployer_address + @property + def is_external(self) -> str: + """Get the contract address of the smart contract. + + Returns: + The contract address. + + """ + return self._model.is_external + @property def type(self) -> Type: """Get the type of the smart contract. @@ -373,6 +398,105 @@ def read( ) return cls._convert_solidity_value(model) + @classmethod + def update( + cls, + contract_name: str, + contract_address: str, + network_id: str, + abi: list[dict], + ) -> "SmartContract": + """Update an existing SmartContract. + + Args: + network_id: The ID of the network. + contract_name: The name of the smart contract. + contract_address: The address of the smart contract. + abi: The ABI of the smart contract. + + Returns: + The updated smart contract. + + """ + abi_json = None + + if abi: + abi_json = json.dumps(abi, separators=(",", ":")) + + update_smart_contract_request = UpdateSmartContractRequest( + abi=abi_json, + contract_name=contract_name, + ) + + model = Cdp.api_clients.smart_contracts.update_smart_contract( + contract_address=contract_address, + network_id=network_id, + update_smart_contract_request=update_smart_contract_request, + ) + + return cls(model) + + @classmethod + def register( + cls, + contract_name: str, + contract_address: str, + network_id: str, + abi: list[dict], + ) -> "SmartContract": + """Register a new SmartContract. + + Args: + network_id: The ID of the network. + contract_name: The name of the smart contract. + contract_address: The address of the smart contract. + abi: The ABI of the smart contract. + + Returns: + The registered smart contract. + + """ + abi_json = None + + if abi: + abi_json = json.dumps(abi, separators=(",", ":")) + + register_smart_contract_request = RegisterSmartContractRequest( + abi=abi_json, + contract_name=contract_name, + ) + + model = Cdp.api_clients.smart_contracts.register_smart_contract( + contract_address=contract_address, + network_id=network_id, + register_smart_contract_request=register_smart_contract_request, + ) + + return cls(model) + + @classmethod + def list(cls) -> Iterator["SmartContract"]: + """List smart contracts. + + Returns: + Iterator[SmartContract]: An iterator of smart contract objects. + + """ + while True: + page = None + + response: SmartContractList = Cdp.api_clients.smart_contracts.list_smart_contracts( + page=page + ) + + for smart_contract_model in response.data: + yield cls(smart_contract_model) + + if not response.has_more: + break + + page = response.next_page + @classmethod def _convert_solidity_value(cls, solidity_value: SolidityValue) -> Any: type_ = solidity_value.type diff --git a/cdp/wallet_address.py b/cdp/wallet_address.py index fe9a0c6..14865e4 100644 --- a/cdp/wallet_address.py +++ b/cdp/wallet_address.py @@ -201,7 +201,9 @@ def invoke_contract( normalized_amount = Decimal(amount) if amount else Decimal("0") if normalized_amount > 0.0 and not asset_id: - raise ValueError("Asset ID is required for contract invocation if an amount is provided") + raise ValueError( + "Asset ID is required for contract invocation if an amount is provided" + ) if amount and asset_id: self._ensure_sufficient_balance(normalized_amount, asset_id) diff --git a/tests/factories/smart_contract_factory.py b/tests/factories/smart_contract_factory.py index efa2bf6..b397cbf 100644 --- a/tests/factories/smart_contract_factory.py +++ b/tests/factories/smart_contract_factory.py @@ -23,8 +23,9 @@ def _create_smart_contract_model(status="complete"): deployer_address="0xdeployeraddress", type="erc20", options=smart_contract_options, - abi='{"abi": "data"}', + abi='{"abi":"data"}', transaction=transaction_model_factory(status), + is_external=False, ) return _create_smart_contract_model diff --git a/tests/test_smart_contract.py b/tests/test_smart_contract.py index f07d5d4..a50ceae 100644 --- a/tests/test_smart_contract.py +++ b/tests/test_smart_contract.py @@ -1,8 +1,11 @@ +import json from unittest.mock import ANY, Mock, call, patch import pytest +from cdp.client.models.register_smart_contract_request import RegisterSmartContractRequest from cdp.client.models.solidity_value import SolidityValue +from cdp.client.models.update_smart_contract_request import UpdateSmartContractRequest from cdp.smart_contract import SmartContract @@ -1626,3 +1629,79 @@ def test_read_pure_int8_without_abi(mock_api_clients): contract_address="0x1234567890123456789012345678901234567890", read_contract_request=ANY, ) + + +@patch("cdp.Cdp.api_clients") +def test_register_smart_contract(mock_api_clients, smart_contract_factory): + """Test the registration of a SmartContract object.""" + mock_register_contract = Mock() + expected_smart_contract = smart_contract_factory()._model + mock_register_contract.return_value = expected_smart_contract + mock_api_clients.smart_contracts.register_smart_contract = mock_register_contract + + contract_address = expected_smart_contract.contract_address + network_id = expected_smart_contract.network_id + contract_name = expected_smart_contract.contract_name + abi_json = json.loads(expected_smart_contract.abi) + abi = expected_smart_contract.abi + + smart_contract = SmartContract.register( + abi=abi_json, + contract_name=contract_name, + contract_address=contract_address, + network_id=network_id, + ) + + assert isinstance(smart_contract, SmartContract) + mock_register_contract.assert_called_once_with( + contract_address=contract_address, + network_id=network_id, + register_smart_contract_request=RegisterSmartContractRequest( + abi=abi, contract_name=contract_name + ), + ) + + _validate_smart_contract(smart_contract, expected_smart_contract) + + +@patch("cdp.Cdp.api_clients") +def test_update_smart_contract(mock_api_clients, smart_contract_factory, all_read_types_abi): + """Test the update of a SmartContract object.""" + mock_updated_contract = Mock() + mock_api_clients.smart_contracts.update_smart_contract = mock_updated_contract + contract_name = "test-contract-2" + abi = '{"abi":"data2"}' + abi_json = json.loads(abi) + + expected_smart_contract = smart_contract_factory()._model + expected_smart_contract.contract_name = contract_name + expected_smart_contract.abi = abi + mock_updated_contract.return_value = expected_smart_contract + contract_address = expected_smart_contract.contract_address + network_id = expected_smart_contract.network_id + + smart_contract = SmartContract.update( + abi=abi_json, + contract_name=contract_name, + contract_address=contract_address, + network_id=network_id, + ) + + assert isinstance(smart_contract, SmartContract) + mock_updated_contract.assert_called_once_with( + contract_address=contract_address, + network_id=network_id, + update_smart_contract_request=UpdateSmartContractRequest( + abi=abi, contract_name=contract_name + ), + ) + + _validate_smart_contract(smart_contract, expected_smart_contract) + + +def _validate_smart_contract(returned_smart_contract, expected_smart_contract): + assert returned_smart_contract.network_id == expected_smart_contract.network_id + assert returned_smart_contract.contract_address == expected_smart_contract.contract_address + assert returned_smart_contract.contract_name == expected_smart_contract.contract_name + assert returned_smart_contract.abi == json.loads(expected_smart_contract.abi) + assert returned_smart_contract.is_external == expected_smart_contract.is_external diff --git a/tests/test_wallet_address.py b/tests/test_wallet_address.py index 1f8376d..9b3e75c 100644 --- a/tests/test_wallet_address.py +++ b/tests/test_wallet_address.py @@ -480,7 +480,9 @@ def test_invoke_contract_with_invalid_input( """Test the invoke_contract method raises an error with invalid input.""" wallet_address_with_key = wallet_address_factory(key=True) - with pytest.raises(Exception, match="Asset ID is required for contract invocation if an amount is provided"): + with pytest.raises( + Exception, match="Asset ID is required for contract invocation if an amount is provided" + ): wallet_address_with_key.invoke_contract( contract_address="0xcontractaddress", method="testMethod", @@ -490,13 +492,11 @@ def test_invoke_contract_with_invalid_input( ) -@ patch("cdp.wallet_address.ContractInvocation") -@ patch("cdp.Cdp.api_clients") -@ patch("cdp.Cdp.use_server_signer", False) +@patch("cdp.wallet_address.ContractInvocation") +@patch("cdp.Cdp.api_clients") +@patch("cdp.Cdp.use_server_signer", False) def test_invoke_contract_api_error( mock_api_clients, mock_contract_invocation, wallet_address_factory, balance_model_factory - - ): """Test the invoke_contract method raises an error when the create API call fails.""" wallet_address_with_key = wallet_address_factory(key=True) From f6ed73fc8d70a7138bbeb4b6a4edc7572807c64c Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Mon, 16 Dec 2024 23:51:37 -0800 Subject: [PATCH 2/8] update --- cdp/smart_contract.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cdp/smart_contract.py b/cdp/smart_contract.py index 8242736..b2eaf3e 100644 --- a/cdp/smart_contract.py +++ b/cdp/smart_contract.py @@ -401,10 +401,10 @@ def read( @classmethod def update( cls, - contract_name: str, contract_address: str, network_id: str, - abi: list[dict], + contract_name: str | None = None, + abi: list[dict] | None = None, ) -> "SmartContract": """Update an existing SmartContract. @@ -439,10 +439,10 @@ def update( @classmethod def register( cls, - contract_name: str, contract_address: str, network_id: str, abi: list[dict], + contract_name: str | None = None, ) -> "SmartContract": """Register a new SmartContract. From 8aed244c0c4d15bb2d91dc3b4290dc1b2cfacade Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 17 Dec 2024 11:55:26 -0800 Subject: [PATCH 3/8] update --- cdp/smart_contract.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdp/smart_contract.py b/cdp/smart_contract.py index b2eaf3e..f1fa4fa 100644 --- a/cdp/smart_contract.py +++ b/cdp/smart_contract.py @@ -157,7 +157,7 @@ def deployer_address(self) -> str: return self._model.deployer_address @property - def is_external(self) -> str: + def is_external(self) -> bool: """Get the contract address of the smart contract. Returns: From fd6120150871dbe732d30b890bf41959ab8f4b6e Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 17 Dec 2024 12:40:50 -0800 Subject: [PATCH 4/8] update smart contract api --- cdp/client/api/smart_contracts_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdp/client/api/smart_contracts_api.py b/cdp/client/api/smart_contracts_api.py index 3fe3ac2..ac7096e 100644 --- a/cdp/client/api/smart_contracts_api.py +++ b/cdp/client/api/smart_contracts_api.py @@ -2123,7 +2123,7 @@ def _update_smart_contract_serialize( ] return self.api_client.param_serialize( - method='PATCH', + method='PUT', resource_path='/v1/networks/{network_id}/smart_contracts/{contract_address}', path_params=_path_params, query_params=_query_params, From 66ebef8c98d7f5810256863d3f7c41cbd0dcae58 Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 17 Dec 2024 14:39:20 -0800 Subject: [PATCH 5/8] return None for the external optional fields --- cdp/smart_contract.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cdp/smart_contract.py b/cdp/smart_contract.py index f1fa4fa..dd5379c 100644 --- a/cdp/smart_contract.py +++ b/cdp/smart_contract.py @@ -117,13 +117,15 @@ def network_id(self) -> str: return self._model.network_id @property - def wallet_id(self) -> str: + def wallet_id(self) -> str | None: """Get the wallet ID that deployed the smart contract. Returns: The wallet ID. """ + if self._model.is_external: + return None return self._model.wallet_id @property @@ -147,13 +149,15 @@ def contract_name(self) -> str: return self._model.contract_name @property - def deployer_address(self) -> str: + def deployer_address(self) -> str | None: """Get the deployer address of the smart contract. Returns: The deployer address. """ + if self._model.is_external: + return None return self._model.deployer_address @property @@ -180,7 +184,7 @@ def type(self) -> Type: return self.Type(self._model.type) @property - def options(self) -> TokenContractOptions | NFTContractOptions | MultiTokenContractOptions: + def options(self) -> TokenContractOptions | NFTContractOptions | MultiTokenContractOptions | None: """Get the options of the smart contract. Returns: @@ -190,6 +194,8 @@ 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._model.options is None or self._model.options.actual_instance is None: raise ValueError("Smart contract options are not set") @@ -221,6 +227,8 @@ def transaction(self) -> Transaction | None: Transaction: The transaction. """ + if self._model.is_external: + return None if self._transaction is None and self._model.transaction is not None: self._update_transaction(self._model) return self._transaction From 391a4d057bf54ea63d2e3d97a76d02f43ff2fdc3 Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 17 Dec 2024 16:52:46 -0800 Subject: [PATCH 6/8] 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.""" From eafcf64420d15fa044a003f2730b10b62661bafe Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 17 Dec 2024 16:57:22 -0800 Subject: [PATCH 7/8] fix lint --- cdp/smart_contract.py | 4 +++- tests/factories/smart_contract_factory.py | 24 +++++++++++------------ tests/test_smart_contract.py | 18 ++++++++++++++--- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/cdp/smart_contract.py b/cdp/smart_contract.py index b316f5c..bd5689c 100644 --- a/cdp/smart_contract.py +++ b/cdp/smart_contract.py @@ -180,7 +180,9 @@ def type(self) -> Type: return self.Type(self._model.type) @property - def options(self) -> TokenContractOptions | NFTContractOptions | MultiTokenContractOptions | None: + def options( + self, + ) -> TokenContractOptions | NFTContractOptions | MultiTokenContractOptions | None: """Get the options of the smart contract. Returns: diff --git a/tests/factories/smart_contract_factory.py b/tests/factories/smart_contract_factory.py index 8a8aa1f..77541ef 100644 --- a/tests/factories/smart_contract_factory.py +++ b/tests/factories/smart_contract_factory.py @@ -30,23 +30,23 @@ 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 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 diff --git a/tests/test_smart_contract.py b/tests/test_smart_contract.py index 73a5c15..cf2a03a 100644 --- a/tests/test_smart_contract.py +++ b/tests/test_smart_contract.py @@ -37,6 +37,7 @@ 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() @@ -49,8 +50,11 @@ def test_external_smart_contract_properties(external_smart_contract_factory): 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 + 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): @@ -100,12 +104,14 @@ 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): """Test the reloading of a SmartContract object.""" @@ -124,12 +130,14 @@ 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") @patch("cdp.smart_contract.time.time") @@ -155,12 +163,14 @@ 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") @patch("cdp.smart_contract.time.time") @@ -188,11 +198,13 @@ 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') + smart_contract.sign("key") + def test_smart_contract_str_representation(smart_contract_factory): """Test the string representation of a SmartContract object.""" From 280d63475ab5f076e3e3f0e0cf7db3b19bf348fc Mon Sep 17 00:00:00 2001 From: Jianlun Zhong Date: Tue, 17 Dec 2024 17:01:00 -0800 Subject: [PATCH 8/8] Update signingkey