From 7c1024f61f7e619039636f1a3da3ba42caa8b6f1 Mon Sep 17 00:00:00 2001 From: Alexander Stone Date: Thu, 31 Oct 2024 10:30:36 -0700 Subject: [PATCH] chore: Release V0.10.0 (#39) * feat: Support waiting for faucet transactions (#38) * chore: Bump OpenAPI client * chore: Add network_id to Transaction resource * chore: Update faucet transaction payload This updates the faucet transaction payload to reflect what our API now returns. * feat: Support fetching faucet transaction status * chore: Add status and network to faucet transaction string * chore: Fix typos * chore: Prepare v0.10.0 release --- CHANGELOG.md | 6 + README.md | 6 + cdp/__version__.py | 2 +- cdp/address.py | 5 +- cdp/client/__init__.py | 12 +- cdp/client/api/__init__.py | 1 + cdp/client/api/addresses_api.py | 9 +- cdp/client/api/external_addresses_api.py | 307 +++- cdp/client/api/fund_api.py | 1240 +++++++++++++++++ cdp/client/api/onchain_identity_api.py | 22 +- cdp/client/models/__init__.py | 11 +- .../models/create_fund_operation_request.py | 91 ++ .../models/create_fund_quote_request.py | 89 ++ cdp/client/models/crypto_amount.py | 93 ++ cdp/client/models/faucet_transaction.py | 10 +- cdp/client/models/fiat_amount.py | 89 ++ cdp/client/models/fund_operation.py | 120 ++ cdp/client/models/fund_operation_fees.py | 97 ++ cdp/client/models/fund_operation_list.py | 101 ++ cdp/client/models/fund_quote.py | 114 ++ cdp/client/models/onchain_name.py | 21 +- cdp/faucet_transaction.py | 96 +- cdp/transaction.py | 5 + docs/conf.py | 2 +- pyproject.toml | 2 +- tests/factories/faucet_transaction_factory.py | 37 + tests/factories/transaction_factory.py | 2 +- tests/test_address.py | 18 +- tests/test_faucet_transaction.py | 105 ++ tests/test_transaction.py | 1 + 30 files changed, 2678 insertions(+), 36 deletions(-) create mode 100644 cdp/client/api/fund_api.py create mode 100644 cdp/client/models/create_fund_operation_request.py create mode 100644 cdp/client/models/create_fund_quote_request.py create mode 100644 cdp/client/models/crypto_amount.py create mode 100644 cdp/client/models/fiat_amount.py create mode 100644 cdp/client/models/fund_operation.py create mode 100644 cdp/client/models/fund_operation_fees.py create mode 100644 cdp/client/models/fund_operation_list.py create mode 100644 cdp/client/models/fund_quote.py create mode 100644 tests/factories/faucet_transaction_factory.py create mode 100644 tests/test_faucet_transaction.py diff --git a/CHANGELOG.md b/CHANGELOG.md index c7e0caa..0847e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased +## [0.10.0] - 2024-10-31 + +### Changed +- Make faucet transactions async i.e. using `faucet_tx.wait()` to wait for the transaction to be confirmed. + - This will make the SDK more consistent and make faucet transactions more reliable. + ## [0.0.9] - 2024-10-29 ### Fixed diff --git a/README.md b/README.md index 9fc8dae..f46bd48 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,9 @@ testnet ETH. You are allowed one faucet claim per 24-hour window. # Fund the wallet with a faucet transaction. faucet_tx = wallet1.faucet() +# Wait for the faucet transaction to complete. +faucet_tx.wait() + print(f"Faucet transaction successfully completed: {faucet_tx}") ``` @@ -135,6 +138,9 @@ print(f"Wallet successfully created: {wallet3}") # Fund the wallet with USDC with a faucet transaction. usdc_faucet_tx = wallet1.faucet("usdc") +# Wait for the faucet transaction to complete. +usdc_faucet_tx.wait() + print(f"Faucet transaction successfully completed: {usdc_faucet_tx}") transfer = wallet1.transfer(0.00001, "usdc", wallet3, gasless=True).wait() diff --git a/cdp/__version__.py b/cdp/__version__.py index 00ec2dc..61fb31c 100644 --- a/cdp/__version__.py +++ b/cdp/__version__.py @@ -1 +1 @@ -__version__ = "0.0.9" +__version__ = "0.10.0" diff --git a/cdp/address.py b/cdp/address.py index da5a652..e8a24a9 100644 --- a/cdp/address.py +++ b/cdp/address.py @@ -65,7 +65,10 @@ def faucet(self, asset_id=None) -> FaucetTransaction: """ model = Cdp.api_clients.external_addresses.request_external_faucet_funds( - network_id=self.network_id, address_id=self.address_id, asset_id=asset_id + network_id=self.network_id, + address_id=self.address_id, + asset_id=asset_id, + skip_wait=True ) return FaucetTransaction(model) diff --git a/cdp/client/__init__.py b/cdp/client/__init__.py index 4fbe28c..317f584 100644 --- a/cdp/client/__init__.py +++ b/cdp/client/__init__.py @@ -23,6 +23,7 @@ from cdp.client.api.contract_events_api import ContractEventsApi from cdp.client.api.contract_invocations_api import ContractInvocationsApi from cdp.client.api.external_addresses_api import ExternalAddressesApi +from cdp.client.api.fund_api import FundApi from cdp.client.api.networks_api import NetworksApi from cdp.client.api.onchain_identity_api import OnchainIdentityApi from cdp.client.api.server_signers_api import ServerSignersApi @@ -67,6 +68,8 @@ from cdp.client.models.contract_invocation_list import ContractInvocationList from cdp.client.models.create_address_request import CreateAddressRequest from cdp.client.models.create_contract_invocation_request import CreateContractInvocationRequest +from cdp.client.models.create_fund_operation_request import CreateFundOperationRequest +from cdp.client.models.create_fund_quote_request import CreateFundQuoteRequest from cdp.client.models.create_payload_signature_request import CreatePayloadSignatureRequest from cdp.client.models.create_server_signer_request import CreateServerSignerRequest from cdp.client.models.create_smart_contract_request import CreateSmartContractRequest @@ -77,10 +80,12 @@ from cdp.client.models.create_wallet_request_wallet import CreateWalletRequestWallet from cdp.client.models.create_wallet_webhook_request import CreateWalletWebhookRequest from cdp.client.models.create_webhook_request import CreateWebhookRequest +from cdp.client.models.crypto_amount import CryptoAmount from cdp.client.models.deploy_smart_contract_request import DeploySmartContractRequest from cdp.client.models.erc20_transfer_event import ERC20TransferEvent from cdp.client.models.erc721_transfer_event import ERC721TransferEvent from cdp.client.models.error import Error +from cdp.client.models.ethereum_token_transfer import EthereumTokenTransfer from cdp.client.models.ethereum_transaction import EthereumTransaction from cdp.client.models.ethereum_transaction_access import EthereumTransactionAccess from cdp.client.models.ethereum_transaction_access_list import EthereumTransactionAccessList @@ -91,6 +96,11 @@ from cdp.client.models.fetch_historical_staking_balances200_response import FetchHistoricalStakingBalances200Response from cdp.client.models.fetch_staking_rewards200_response import FetchStakingRewards200Response from cdp.client.models.fetch_staking_rewards_request import FetchStakingRewardsRequest +from cdp.client.models.fiat_amount import FiatAmount +from cdp.client.models.fund_operation import FundOperation +from cdp.client.models.fund_operation_fees import FundOperationFees +from cdp.client.models.fund_operation_list import FundOperationList +from cdp.client.models.fund_quote import FundQuote from cdp.client.models.get_staking_context_request import GetStakingContextRequest from cdp.client.models.historical_balance import HistoricalBalance from cdp.client.models.multi_token_contract_options import MultiTokenContractOptions @@ -99,7 +109,6 @@ from cdp.client.models.network_identifier import NetworkIdentifier from cdp.client.models.onchain_name import OnchainName from cdp.client.models.onchain_name_list import OnchainNameList -from cdp.client.models.onchain_name_text_records_inner import OnchainNameTextRecordsInner 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 @@ -128,6 +137,7 @@ from cdp.client.models.staking_reward_format import StakingRewardFormat from cdp.client.models.staking_reward_usd_value import StakingRewardUSDValue from cdp.client.models.token_contract_options import TokenContractOptions +from cdp.client.models.token_transfer_type import TokenTransferType from cdp.client.models.trade import Trade from cdp.client.models.trade_list import TradeList from cdp.client.models.transaction import Transaction diff --git a/cdp/client/api/__init__.py b/cdp/client/api/__init__.py index 221b4a3..ce5dea3 100644 --- a/cdp/client/api/__init__.py +++ b/cdp/client/api/__init__.py @@ -7,6 +7,7 @@ from cdp.client.api.contract_events_api import ContractEventsApi from cdp.client.api.contract_invocations_api import ContractInvocationsApi from cdp.client.api.external_addresses_api import ExternalAddressesApi +from cdp.client.api.fund_api import FundApi from cdp.client.api.networks_api import NetworksApi from cdp.client.api.onchain_identity_api import OnchainIdentityApi from cdp.client.api.server_signers_api import ServerSignersApi diff --git a/cdp/client/api/addresses_api.py b/cdp/client/api/addresses_api.py index 3c6fedd..dca4fb9 100644 --- a/cdp/client/api/addresses_api.py +++ b/cdp/client/api/addresses_api.py @@ -2391,7 +2391,7 @@ def request_faucet_funds( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> FaucetTransaction: - """Request faucet funds for onchain address. + """(Deprecated) Request faucet funds for onchain address. Request faucet funds to be sent to onchain address. @@ -2422,6 +2422,7 @@ def request_faucet_funds( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("POST /v1/wallets/{wallet_id}/addresses/{address_id}/faucet is deprecated.", DeprecationWarning) _param = self._request_faucet_funds_serialize( wallet_id=wallet_id, @@ -2466,7 +2467,7 @@ def request_faucet_funds_with_http_info( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> ApiResponse[FaucetTransaction]: - """Request faucet funds for onchain address. + """(Deprecated) Request faucet funds for onchain address. Request faucet funds to be sent to onchain address. @@ -2497,6 +2498,7 @@ def request_faucet_funds_with_http_info( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("POST /v1/wallets/{wallet_id}/addresses/{address_id}/faucet is deprecated.", DeprecationWarning) _param = self._request_faucet_funds_serialize( wallet_id=wallet_id, @@ -2541,7 +2543,7 @@ def request_faucet_funds_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """Request faucet funds for onchain address. + """(Deprecated) Request faucet funds for onchain address. Request faucet funds to be sent to onchain address. @@ -2572,6 +2574,7 @@ def request_faucet_funds_without_preload_content( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("POST /v1/wallets/{wallet_id}/addresses/{address_id}/faucet is deprecated.", DeprecationWarning) _param = self._request_faucet_funds_serialize( wallet_id=wallet_id, diff --git a/cdp/client/api/external_addresses_api.py b/cdp/client/api/external_addresses_api.py index 197bf46..1975530 100644 --- a/cdp/client/api/external_addresses_api.py +++ b/cdp/client/api/external_addresses_api.py @@ -16,7 +16,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from typing_extensions import Annotated -from pydantic import Field, StrictStr +from pydantic import Field, StrictBool, StrictStr from typing import Optional from typing_extensions import Annotated from cdp.client.models.address_balance_list import AddressBalanceList @@ -329,6 +329,294 @@ def _get_external_address_balance_serialize( + @validate_call + def get_faucet_transaction( + 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 faucet transaction for")], + tx_hash: Annotated[StrictStr, Field(description="The hash of the faucet transaction")], + _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, + ) -> FaucetTransaction: + """Get the status of a faucet transaction + + Get the status of a faucet transaction + + :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 faucet transaction for (required) + :type address_id: str + :param tx_hash: The hash of the faucet transaction (required) + :type tx_hash: 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_faucet_transaction_serialize( + network_id=network_id, + address_id=address_id, + tx_hash=tx_hash, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FaucetTransaction", + } + 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_faucet_transaction_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 faucet transaction for")], + tx_hash: Annotated[StrictStr, Field(description="The hash of the faucet transaction")], + _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[FaucetTransaction]: + """Get the status of a faucet transaction + + Get the status of a faucet transaction + + :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 faucet transaction for (required) + :type address_id: str + :param tx_hash: The hash of the faucet transaction (required) + :type tx_hash: 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_faucet_transaction_serialize( + network_id=network_id, + address_id=address_id, + tx_hash=tx_hash, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FaucetTransaction", + } + 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_faucet_transaction_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 faucet transaction for")], + tx_hash: Annotated[StrictStr, Field(description="The hash of the faucet transaction")], + _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 status of a faucet transaction + + Get the status of a faucet transaction + + :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 faucet transaction for (required) + :type address_id: str + :param tx_hash: The hash of the faucet transaction (required) + :type tx_hash: 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_faucet_transaction_serialize( + network_id=network_id, + address_id=address_id, + tx_hash=tx_hash, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FaucetTransaction", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_faucet_transaction_serialize( + self, + network_id, + address_id, + tx_hash, + _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]] = {} + _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 + if tx_hash is not None: + _path_params['tx_hash'] = tx_hash + # 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}/faucet/{tx_hash}', + 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 + ) + + + + @validate_call def list_external_address_balances( self, @@ -625,6 +913,7 @@ def request_external_faucet_funds( network_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], address_id: Annotated[StrictStr, Field(description="The onchain address of the address that is being fetched.")], asset_id: Annotated[Optional[StrictStr], Field(description="The ID of the asset to transfer from the faucet.")] = None, + skip_wait: Annotated[Optional[StrictBool], Field(description="Whether to skip waiting for the transaction to be mined. This will become the default behavior in the future.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -648,6 +937,8 @@ def request_external_faucet_funds( :type address_id: str :param asset_id: The ID of the asset to transfer from the faucet. :type asset_id: str + :param skip_wait: Whether to skip waiting for the transaction to be mined. This will become the default behavior in the future. + :type skip_wait: bool :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 @@ -674,6 +965,7 @@ def request_external_faucet_funds( network_id=network_id, address_id=address_id, asset_id=asset_id, + skip_wait=skip_wait, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -700,6 +992,7 @@ def request_external_faucet_funds_with_http_info( network_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], address_id: Annotated[StrictStr, Field(description="The onchain address of the address that is being fetched.")], asset_id: Annotated[Optional[StrictStr], Field(description="The ID of the asset to transfer from the faucet.")] = None, + skip_wait: Annotated[Optional[StrictBool], Field(description="Whether to skip waiting for the transaction to be mined. This will become the default behavior in the future.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -723,6 +1016,8 @@ def request_external_faucet_funds_with_http_info( :type address_id: str :param asset_id: The ID of the asset to transfer from the faucet. :type asset_id: str + :param skip_wait: Whether to skip waiting for the transaction to be mined. This will become the default behavior in the future. + :type skip_wait: bool :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 @@ -749,6 +1044,7 @@ def request_external_faucet_funds_with_http_info( network_id=network_id, address_id=address_id, asset_id=asset_id, + skip_wait=skip_wait, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -775,6 +1071,7 @@ def request_external_faucet_funds_without_preload_content( network_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], address_id: Annotated[StrictStr, Field(description="The onchain address of the address that is being fetched.")], asset_id: Annotated[Optional[StrictStr], Field(description="The ID of the asset to transfer from the faucet.")] = None, + skip_wait: Annotated[Optional[StrictBool], Field(description="Whether to skip waiting for the transaction to be mined. This will become the default behavior in the future.")] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], @@ -798,6 +1095,8 @@ def request_external_faucet_funds_without_preload_content( :type address_id: str :param asset_id: The ID of the asset to transfer from the faucet. :type asset_id: str + :param skip_wait: Whether to skip waiting for the transaction to be mined. This will become the default behavior in the future. + :type skip_wait: bool :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 @@ -824,6 +1123,7 @@ def request_external_faucet_funds_without_preload_content( network_id=network_id, address_id=address_id, asset_id=asset_id, + skip_wait=skip_wait, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, @@ -845,6 +1145,7 @@ def _request_external_faucet_funds_serialize( network_id, address_id, asset_id, + skip_wait, _request_auth, _content_type, _headers, @@ -873,6 +1174,10 @@ def _request_external_faucet_funds_serialize( _query_params.append(('asset_id', asset_id)) + if skip_wait is not None: + + _query_params.append(('skip_wait', skip_wait)) + # process the header parameters # process the form parameters # process the body parameter diff --git a/cdp/client/api/fund_api.py b/cdp/client/api/fund_api.py new file mode 100644 index 0000000..1c62f38 --- /dev/null +++ b/cdp/client/api/fund_api.py @@ -0,0 +1,1240 @@ +# 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 + +import warnings +from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt +from typing import Any, Dict, List, Optional, Tuple, Union +from typing_extensions import Annotated + +from pydantic import Field, StrictInt, StrictStr +from typing import Optional +from typing_extensions import Annotated +from cdp.client.models.create_fund_operation_request import CreateFundOperationRequest +from cdp.client.models.create_fund_quote_request import CreateFundQuoteRequest +from cdp.client.models.fund_operation import FundOperation +from cdp.client.models.fund_operation_list import FundOperationList +from cdp.client.models.fund_quote import FundQuote + +from cdp.client.api_client import ApiClient, RequestSerialized +from cdp.client.api_response import ApiResponse +from cdp.client.rest import RESTResponseType + + +class FundApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_fund_operation( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address to be funded.")], + create_fund_operation_request: CreateFundOperationRequest, + _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, + ) -> FundOperation: + """Create a new fund operation. + + Create a new fund operation with an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address to be funded. (required) + :type address_id: str + :param create_fund_operation_request: (required) + :type create_fund_operation_request: CreateFundOperationRequest + :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._create_fund_operation_serialize( + wallet_id=wallet_id, + address_id=address_id, + create_fund_operation_request=create_fund_operation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperation", + } + 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 create_fund_operation_with_http_info( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address to be funded.")], + create_fund_operation_request: CreateFundOperationRequest, + _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[FundOperation]: + """Create a new fund operation. + + Create a new fund operation with an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address to be funded. (required) + :type address_id: str + :param create_fund_operation_request: (required) + :type create_fund_operation_request: CreateFundOperationRequest + :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._create_fund_operation_serialize( + wallet_id=wallet_id, + address_id=address_id, + create_fund_operation_request=create_fund_operation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperation", + } + 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 create_fund_operation_without_preload_content( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address to be funded.")], + create_fund_operation_request: CreateFundOperationRequest, + _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: + """Create a new fund operation. + + Create a new fund operation with an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address to be funded. (required) + :type address_id: str + :param create_fund_operation_request: (required) + :type create_fund_operation_request: CreateFundOperationRequest + :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._create_fund_operation_serialize( + wallet_id=wallet_id, + address_id=address_id, + create_fund_operation_request=create_fund_operation_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperation", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_fund_operation_serialize( + self, + wallet_id, + address_id, + create_fund_operation_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]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if wallet_id is not None: + _path_params['wallet_id'] = wallet_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 + if create_fund_operation_request is not None: + _body_params = create_fund_operation_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] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/wallets/{wallet_id}/addresses/{address_id}/fund_operations', + 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 + ) + + + + + @validate_call + def create_fund_quote( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address to be funded.")], + create_fund_quote_request: CreateFundQuoteRequest, + _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, + ) -> FundQuote: + """Create a Fund Operation quote. + + Create a new fund operation with an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address to be funded. (required) + :type address_id: str + :param create_fund_quote_request: (required) + :type create_fund_quote_request: CreateFundQuoteRequest + :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._create_fund_quote_serialize( + wallet_id=wallet_id, + address_id=address_id, + create_fund_quote_request=create_fund_quote_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundQuote", + } + 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 create_fund_quote_with_http_info( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address to be funded.")], + create_fund_quote_request: CreateFundQuoteRequest, + _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[FundQuote]: + """Create a Fund Operation quote. + + Create a new fund operation with an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address to be funded. (required) + :type address_id: str + :param create_fund_quote_request: (required) + :type create_fund_quote_request: CreateFundQuoteRequest + :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._create_fund_quote_serialize( + wallet_id=wallet_id, + address_id=address_id, + create_fund_quote_request=create_fund_quote_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundQuote", + } + 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 create_fund_quote_without_preload_content( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address to be funded.")], + create_fund_quote_request: CreateFundQuoteRequest, + _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: + """Create a Fund Operation quote. + + Create a new fund operation with an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address to be funded. (required) + :type address_id: str + :param create_fund_quote_request: (required) + :type create_fund_quote_request: CreateFundQuoteRequest + :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._create_fund_quote_serialize( + wallet_id=wallet_id, + address_id=address_id, + create_fund_quote_request=create_fund_quote_request, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundQuote", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_fund_quote_serialize( + self, + wallet_id, + address_id, + create_fund_quote_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]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if wallet_id is not None: + _path_params['wallet_id'] = wallet_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 + if create_fund_quote_request is not None: + _body_params = create_fund_quote_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] = [ + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/v1/wallets/{wallet_id}/addresses/{address_id}/fund_operations/quote', + 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 + ) + + + + + @validate_call + def get_fund_operation( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address of the address that created the fund operation.")], + fund_operation_id: Annotated[StrictStr, Field(description="The ID of the fund operation to fetch.")], + _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, + ) -> FundOperation: + """Get fund operation. + + Get fund operation. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address of the address that created the fund operation. (required) + :type address_id: str + :param fund_operation_id: The ID of the fund operation to fetch. (required) + :type fund_operation_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_fund_operation_serialize( + wallet_id=wallet_id, + address_id=address_id, + fund_operation_id=fund_operation_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperation", + } + 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_fund_operation_with_http_info( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address of the address that created the fund operation.")], + fund_operation_id: Annotated[StrictStr, Field(description="The ID of the fund operation to fetch.")], + _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[FundOperation]: + """Get fund operation. + + Get fund operation. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address of the address that created the fund operation. (required) + :type address_id: str + :param fund_operation_id: The ID of the fund operation to fetch. (required) + :type fund_operation_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_fund_operation_serialize( + wallet_id=wallet_id, + address_id=address_id, + fund_operation_id=fund_operation_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperation", + } + 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_fund_operation_without_preload_content( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address of the address that created the fund operation.")], + fund_operation_id: Annotated[StrictStr, Field(description="The ID of the fund operation to fetch.")], + _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 fund operation. + + Get fund operation. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address of the address that created the fund operation. (required) + :type address_id: str + :param fund_operation_id: The ID of the fund operation to fetch. (required) + :type fund_operation_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_fund_operation_serialize( + wallet_id=wallet_id, + address_id=address_id, + fund_operation_id=fund_operation_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperation", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_fund_operation_serialize( + self, + wallet_id, + address_id, + fund_operation_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]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if wallet_id is not None: + _path_params['wallet_id'] = wallet_id + if address_id is not None: + _path_params['address_id'] = address_id + if fund_operation_id is not None: + _path_params['fund_operation_id'] = fund_operation_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/wallets/{wallet_id}/addresses/{address_id}/fund_operations/{fund_operation_id}', + 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 + ) + + + + + @validate_call + def list_fund_operations( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address of the address to list fund operations for.")], + limit: Annotated[Optional[StrictInt], Field(description="A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.")] = None, + page: Annotated[Optional[Annotated[str, Field(strict=True, max_length=5000)]], Field(description="A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.")] = 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, + ) -> FundOperationList: + """List fund operations for an address. + + List fund operations for an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address of the address to list fund operations for. (required) + :type address_id: str + :param limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + :type limit: int + :param page: A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + :type page: 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._list_fund_operations_serialize( + wallet_id=wallet_id, + address_id=address_id, + limit=limit, + page=page, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperationList", + } + 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 list_fund_operations_with_http_info( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address of the address to list fund operations for.")], + limit: Annotated[Optional[StrictInt], Field(description="A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.")] = None, + page: Annotated[Optional[Annotated[str, Field(strict=True, max_length=5000)]], Field(description="A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.")] = 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[FundOperationList]: + """List fund operations for an address. + + List fund operations for an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address of the address to list fund operations for. (required) + :type address_id: str + :param limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + :type limit: int + :param page: A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + :type page: 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._list_fund_operations_serialize( + wallet_id=wallet_id, + address_id=address_id, + limit=limit, + page=page, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperationList", + } + 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 list_fund_operations_without_preload_content( + self, + wallet_id: Annotated[StrictStr, Field(description="The ID of the wallet the address belongs to.")], + address_id: Annotated[StrictStr, Field(description="The onchain address of the address to list fund operations for.")], + limit: Annotated[Optional[StrictInt], Field(description="A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.")] = None, + page: Annotated[Optional[Annotated[str, Field(strict=True, max_length=5000)]], Field(description="A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.")] = 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: + """List fund operations for an address. + + List fund operations for an address. + + :param wallet_id: The ID of the wallet the address belongs to. (required) + :type wallet_id: str + :param address_id: The onchain address of the address to list fund operations for. (required) + :type address_id: str + :param limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. + :type limit: int + :param page: A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. + :type page: 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._list_fund_operations_serialize( + wallet_id=wallet_id, + address_id=address_id, + limit=limit, + page=page, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "FundOperationList", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_fund_operations_serialize( + self, + wallet_id, + address_id, + limit, + page, + _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]] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if wallet_id is not None: + _path_params['wallet_id'] = wallet_id + if address_id is not None: + _path_params['address_id'] = address_id + # process the query parameters + if limit is not None: + + _query_params.append(('limit', limit)) + + if page is not None: + + _query_params.append(('page', page)) + + # 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/wallets/{wallet_id}/addresses/{address_id}/fund_operations', + 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/onchain_identity_api.py b/cdp/client/api/onchain_identity_api.py index 06b80ac..757d351 100644 --- a/cdp/client/api/onchain_identity_api.py +++ b/cdp/client/api/onchain_identity_api.py @@ -16,8 +16,8 @@ from typing import Any, Dict, List, Optional, Tuple, Union from typing_extensions import Annotated -from pydantic import Field, StrictInt, StrictStr -from typing import Optional +from pydantic import Field, StrictInt, StrictStr, field_validator +from typing import List, Optional from typing_extensions import Annotated from cdp.client.models.onchain_name_list import OnchainNameList @@ -44,6 +44,7 @@ def resolve_identity_by_address( 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 identity for")], + roles: Annotated[Optional[List[StrictStr]], Field(description="A filter by role of the names related to this address (managed or owned)")] = None, limit: Annotated[Optional[StrictInt], Field(description="A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.")] = None, page: Annotated[Optional[Annotated[str, Field(strict=True, max_length=5000)]], Field(description="A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.")] = None, _request_timeout: Union[ @@ -67,6 +68,8 @@ def resolve_identity_by_address( :type network_id: str :param address_id: The ID of the address to fetch the identity for (required) :type address_id: str + :param roles: A filter by role of the names related to this address (managed or owned) + :type roles: List[str] :param limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. :type limit: int :param page: A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. @@ -96,6 +99,7 @@ def resolve_identity_by_address( _param = self._resolve_identity_by_address_serialize( network_id=network_id, address_id=address_id, + roles=roles, limit=limit, page=page, _request_auth=_request_auth, @@ -123,6 +127,7 @@ def resolve_identity_by_address_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 identity for")], + roles: Annotated[Optional[List[StrictStr]], Field(description="A filter by role of the names related to this address (managed or owned)")] = None, limit: Annotated[Optional[StrictInt], Field(description="A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.")] = None, page: Annotated[Optional[Annotated[str, Field(strict=True, max_length=5000)]], Field(description="A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.")] = None, _request_timeout: Union[ @@ -146,6 +151,8 @@ def resolve_identity_by_address_with_http_info( :type network_id: str :param address_id: The ID of the address to fetch the identity for (required) :type address_id: str + :param roles: A filter by role of the names related to this address (managed or owned) + :type roles: List[str] :param limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. :type limit: int :param page: A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. @@ -175,6 +182,7 @@ def resolve_identity_by_address_with_http_info( _param = self._resolve_identity_by_address_serialize( network_id=network_id, address_id=address_id, + roles=roles, limit=limit, page=page, _request_auth=_request_auth, @@ -202,6 +210,7 @@ def resolve_identity_by_address_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 identity for")], + roles: Annotated[Optional[List[StrictStr]], Field(description="A filter by role of the names related to this address (managed or owned)")] = None, limit: Annotated[Optional[StrictInt], Field(description="A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.")] = None, page: Annotated[Optional[Annotated[str, Field(strict=True, max_length=5000)]], Field(description="A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results.")] = None, _request_timeout: Union[ @@ -225,6 +234,8 @@ def resolve_identity_by_address_without_preload_content( :type network_id: str :param address_id: The ID of the address to fetch the identity for (required) :type address_id: str + :param roles: A filter by role of the names related to this address (managed or owned) + :type roles: List[str] :param limit: A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10. :type limit: int :param page: A cursor for pagination across multiple pages of results. Don't include this parameter on the first call. Use the next_page value returned in a previous response to request subsequent results. @@ -254,6 +265,7 @@ def resolve_identity_by_address_without_preload_content( _param = self._resolve_identity_by_address_serialize( network_id=network_id, address_id=address_id, + roles=roles, limit=limit, page=page, _request_auth=_request_auth, @@ -276,6 +288,7 @@ def _resolve_identity_by_address_serialize( self, network_id, address_id, + roles, limit, page, _request_auth, @@ -287,6 +300,7 @@ def _resolve_identity_by_address_serialize( _host = None _collection_formats: Dict[str, str] = { + 'roles': 'csv', } _path_params: Dict[str, str] = {} @@ -302,6 +316,10 @@ def _resolve_identity_by_address_serialize( if address_id is not None: _path_params['address_id'] = address_id # process the query parameters + if roles is not None: + + _query_params.append(('roles', roles)) + if limit is not None: _query_params.append(('limit', limit)) diff --git a/cdp/client/models/__init__.py b/cdp/client/models/__init__.py index 6cda9a0..188df88 100644 --- a/cdp/client/models/__init__.py +++ b/cdp/client/models/__init__.py @@ -32,6 +32,8 @@ from cdp.client.models.contract_invocation_list import ContractInvocationList from cdp.client.models.create_address_request import CreateAddressRequest from cdp.client.models.create_contract_invocation_request import CreateContractInvocationRequest +from cdp.client.models.create_fund_operation_request import CreateFundOperationRequest +from cdp.client.models.create_fund_quote_request import CreateFundQuoteRequest from cdp.client.models.create_payload_signature_request import CreatePayloadSignatureRequest from cdp.client.models.create_server_signer_request import CreateServerSignerRequest from cdp.client.models.create_smart_contract_request import CreateSmartContractRequest @@ -42,10 +44,12 @@ from cdp.client.models.create_wallet_request_wallet import CreateWalletRequestWallet from cdp.client.models.create_wallet_webhook_request import CreateWalletWebhookRequest from cdp.client.models.create_webhook_request import CreateWebhookRequest +from cdp.client.models.crypto_amount import CryptoAmount from cdp.client.models.deploy_smart_contract_request import DeploySmartContractRequest from cdp.client.models.erc20_transfer_event import ERC20TransferEvent from cdp.client.models.erc721_transfer_event import ERC721TransferEvent from cdp.client.models.error import Error +from cdp.client.models.ethereum_token_transfer import EthereumTokenTransfer from cdp.client.models.ethereum_transaction import EthereumTransaction from cdp.client.models.ethereum_transaction_access import EthereumTransactionAccess from cdp.client.models.ethereum_transaction_access_list import EthereumTransactionAccessList @@ -56,6 +60,11 @@ from cdp.client.models.fetch_historical_staking_balances200_response import FetchHistoricalStakingBalances200Response from cdp.client.models.fetch_staking_rewards200_response import FetchStakingRewards200Response from cdp.client.models.fetch_staking_rewards_request import FetchStakingRewardsRequest +from cdp.client.models.fiat_amount import FiatAmount +from cdp.client.models.fund_operation import FundOperation +from cdp.client.models.fund_operation_fees import FundOperationFees +from cdp.client.models.fund_operation_list import FundOperationList +from cdp.client.models.fund_quote import FundQuote from cdp.client.models.get_staking_context_request import GetStakingContextRequest from cdp.client.models.historical_balance import HistoricalBalance from cdp.client.models.multi_token_contract_options import MultiTokenContractOptions @@ -64,7 +73,6 @@ from cdp.client.models.network_identifier import NetworkIdentifier from cdp.client.models.onchain_name import OnchainName from cdp.client.models.onchain_name_list import OnchainNameList -from cdp.client.models.onchain_name_text_records_inner import OnchainNameTextRecordsInner 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 @@ -93,6 +101,7 @@ from cdp.client.models.staking_reward_format import StakingRewardFormat from cdp.client.models.staking_reward_usd_value import StakingRewardUSDValue from cdp.client.models.token_contract_options import TokenContractOptions +from cdp.client.models.token_transfer_type import TokenTransferType from cdp.client.models.trade import Trade from cdp.client.models.trade_list import TradeList from cdp.client.models.transaction import Transaction diff --git a/cdp/client/models/create_fund_operation_request.py b/cdp/client/models/create_fund_operation_request.py new file mode 100644 index 0000000..adebe8c --- /dev/null +++ b/cdp/client/models/create_fund_operation_request.py @@ -0,0 +1,91 @@ +# 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 import Optional, Set +from typing_extensions import Self + +class CreateFundOperationRequest(BaseModel): + """ + CreateFundOperationRequest + """ # noqa: E501 + amount: StrictStr = Field(description="The amount of the asset to fund the address with in atomic units.") + asset_id: StrictStr = Field(description="The ID of the asset to fund the address with.") + fund_quote_id: Optional[StrictStr] = Field(default=None, description="The Optional ID of the fund quote to fund the address with. If omitted we will generate a quote and immediately execute it.") + __properties: ClassVar[List[str]] = ["amount", "asset_id", "fund_quote_id"] + + 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 CreateFundOperationRequest 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 CreateFundOperationRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "amount": obj.get("amount"), + "asset_id": obj.get("asset_id"), + "fund_quote_id": obj.get("fund_quote_id") + }) + return _obj + + diff --git a/cdp/client/models/create_fund_quote_request.py b/cdp/client/models/create_fund_quote_request.py new file mode 100644 index 0000000..e7f7bda --- /dev/null +++ b/cdp/client/models/create_fund_quote_request.py @@ -0,0 +1,89 @@ +# 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 +from typing import Optional, Set +from typing_extensions import Self + +class CreateFundQuoteRequest(BaseModel): + """ + CreateFundQuoteRequest + """ # noqa: E501 + amount: StrictStr = Field(description="The amount of the asset to fund the address with in atomic units.") + asset_id: StrictStr = Field(description="The ID of the asset to fund the address with.") + __properties: ClassVar[List[str]] = ["amount", "asset_id"] + + 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 CreateFundQuoteRequest 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 CreateFundQuoteRequest from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "amount": obj.get("amount"), + "asset_id": obj.get("asset_id") + }) + return _obj + + diff --git a/cdp/client/models/crypto_amount.py b/cdp/client/models/crypto_amount.py new file mode 100644 index 0000000..9409e43 --- /dev/null +++ b/cdp/client/models/crypto_amount.py @@ -0,0 +1,93 @@ +# 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 +from cdp.client.models.asset import Asset +from typing import Optional, Set +from typing_extensions import Self + +class CryptoAmount(BaseModel): + """ + An amount in cryptocurrency + """ # noqa: E501 + amount: StrictStr = Field(description="The amount of the crypto in atomic units") + asset: Asset + __properties: ClassVar[List[str]] = ["amount", "asset"] + + 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 CryptoAmount 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, + ) + # override the default output from pydantic by calling `to_dict()` of asset + if self.asset: + _dict['asset'] = self.asset.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CryptoAmount from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "amount": obj.get("amount"), + "asset": Asset.from_dict(obj["asset"]) if obj.get("asset") is not None else None + }) + return _obj + + diff --git a/cdp/client/models/faucet_transaction.py b/cdp/client/models/faucet_transaction.py index cfad1a9..848ffa6 100644 --- a/cdp/client/models/faucet_transaction.py +++ b/cdp/client/models/faucet_transaction.py @@ -19,6 +19,7 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List +from cdp.client.models.transaction import Transaction from typing import Optional, Set from typing_extensions import Self @@ -28,7 +29,8 @@ class FaucetTransaction(BaseModel): """ # noqa: E501 transaction_hash: StrictStr = Field(description="The transaction hash of the transaction the faucet created.") transaction_link: StrictStr = Field(description="Link to the transaction on the blockchain explorer.") - __properties: ClassVar[List[str]] = ["transaction_hash", "transaction_link"] + transaction: Transaction + __properties: ClassVar[List[str]] = ["transaction_hash", "transaction_link", "transaction"] model_config = ConfigDict( populate_by_name=True, @@ -69,6 +71,9 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of transaction + if self.transaction: + _dict['transaction'] = self.transaction.to_dict() return _dict @classmethod @@ -82,7 +87,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "transaction_hash": obj.get("transaction_hash"), - "transaction_link": obj.get("transaction_link") + "transaction_link": obj.get("transaction_link"), + "transaction": Transaction.from_dict(obj["transaction"]) if obj.get("transaction") is not None else None }) return _obj diff --git a/cdp/client/models/fiat_amount.py b/cdp/client/models/fiat_amount.py new file mode 100644 index 0000000..3997da7 --- /dev/null +++ b/cdp/client/models/fiat_amount.py @@ -0,0 +1,89 @@ +# 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 +from typing import Optional, Set +from typing_extensions import Self + +class FiatAmount(BaseModel): + """ + An amount in fiat currency + """ # noqa: E501 + amount: StrictStr = Field(description="The amount of the fiat in whole units.") + currency: StrictStr = Field(description="The currency of the fiat") + __properties: ClassVar[List[str]] = ["amount", "currency"] + + 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 FiatAmount 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 FiatAmount from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "amount": obj.get("amount"), + "currency": obj.get("currency") + }) + return _obj + + diff --git a/cdp/client/models/fund_operation.py b/cdp/client/models/fund_operation.py new file mode 100644 index 0000000..ead6042 --- /dev/null +++ b/cdp/client/models/fund_operation.py @@ -0,0 +1,120 @@ +# 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, field_validator +from typing import Any, ClassVar, Dict, List +from cdp.client.models.crypto_amount import CryptoAmount +from cdp.client.models.fiat_amount import FiatAmount +from cdp.client.models.fund_operation_fees import FundOperationFees +from typing import Optional, Set +from typing_extensions import Self + +class FundOperation(BaseModel): + """ + An operation to fund a wallet with crypto + """ # noqa: E501 + fund_operation_id: StrictStr = Field(description="The ID of the fund operation") + network_id: StrictStr = Field(description="The ID of the blockchain network") + wallet_id: StrictStr = Field(description="The ID of the wallet that will receive the crypto") + address_id: StrictStr = Field(description="The ID of the address that will receive the crypto") + crypto_amount: CryptoAmount + fiat_amount: FiatAmount + fees: FundOperationFees + status: StrictStr = Field(description="The status of the fund operation") + __properties: ClassVar[List[str]] = ["fund_operation_id", "network_id", "wallet_id", "address_id", "crypto_amount", "fiat_amount", "fees", "status"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['pending', 'complete', 'failed']): + raise ValueError("must be one of enum values ('pending', 'complete', 'failed')") + return value + + 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 FundOperation 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, + ) + # override the default output from pydantic by calling `to_dict()` of crypto_amount + if self.crypto_amount: + _dict['crypto_amount'] = self.crypto_amount.to_dict() + # override the default output from pydantic by calling `to_dict()` of fiat_amount + if self.fiat_amount: + _dict['fiat_amount'] = self.fiat_amount.to_dict() + # override the default output from pydantic by calling `to_dict()` of fees + if self.fees: + _dict['fees'] = self.fees.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of FundOperation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "fund_operation_id": obj.get("fund_operation_id"), + "network_id": obj.get("network_id"), + "wallet_id": obj.get("wallet_id"), + "address_id": obj.get("address_id"), + "crypto_amount": CryptoAmount.from_dict(obj["crypto_amount"]) if obj.get("crypto_amount") is not None else None, + "fiat_amount": FiatAmount.from_dict(obj["fiat_amount"]) if obj.get("fiat_amount") is not None else None, + "fees": FundOperationFees.from_dict(obj["fees"]) if obj.get("fees") is not None else None, + "status": obj.get("status") + }) + return _obj + + diff --git a/cdp/client/models/fund_operation_fees.py b/cdp/client/models/fund_operation_fees.py new file mode 100644 index 0000000..7601e7e --- /dev/null +++ b/cdp/client/models/fund_operation_fees.py @@ -0,0 +1,97 @@ +# 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 +from typing import Any, ClassVar, Dict, List +from cdp.client.models.crypto_amount import CryptoAmount +from cdp.client.models.fiat_amount import FiatAmount +from typing import Optional, Set +from typing_extensions import Self + +class FundOperationFees(BaseModel): + """ + The fees for a fund operation. + """ # noqa: E501 + buy_fee: FiatAmount + transfer_fee: CryptoAmount + __properties: ClassVar[List[str]] = ["buy_fee", "transfer_fee"] + + 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 FundOperationFees 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, + ) + # override the default output from pydantic by calling `to_dict()` of buy_fee + if self.buy_fee: + _dict['buy_fee'] = self.buy_fee.to_dict() + # override the default output from pydantic by calling `to_dict()` of transfer_fee + if self.transfer_fee: + _dict['transfer_fee'] = self.transfer_fee.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of FundOperationFees from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "buy_fee": FiatAmount.from_dict(obj["buy_fee"]) if obj.get("buy_fee") is not None else None, + "transfer_fee": CryptoAmount.from_dict(obj["transfer_fee"]) if obj.get("transfer_fee") is not None else None + }) + return _obj + + diff --git a/cdp/client/models/fund_operation_list.py b/cdp/client/models/fund_operation_list.py new file mode 100644 index 0000000..3284f65 --- /dev/null +++ b/cdp/client/models/fund_operation_list.py @@ -0,0 +1,101 @@ +# 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, StrictBool, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List +from cdp.client.models.fund_operation import FundOperation +from typing import Optional, Set +from typing_extensions import Self + +class FundOperationList(BaseModel): + """ + Paginated list of fund operations + """ # noqa: E501 + data: List[FundOperation] + has_more: StrictBool = Field(description="True if this list has another page of items after this one that can be fetched.") + next_page: StrictStr = Field(description="The page token to be used to fetch the next page.") + total_count: StrictInt = Field(description="The total number of fund operations") + __properties: ClassVar[List[str]] = ["data", "has_more", "next_page", "total_count"] + + 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 FundOperationList 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, + ) + # override the default output from pydantic by calling `to_dict()` of each item in data (list) + _items = [] + if self.data: + for _item_data in self.data: + if _item_data: + _items.append(_item_data.to_dict()) + _dict['data'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of FundOperationList from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "data": [FundOperation.from_dict(_item) for _item in obj["data"]] if obj.get("data") is not None else None, + "has_more": obj.get("has_more"), + "next_page": obj.get("next_page"), + "total_count": obj.get("total_count") + }) + return _obj + + diff --git a/cdp/client/models/fund_quote.py b/cdp/client/models/fund_quote.py new file mode 100644 index 0000000..2a768d6 --- /dev/null +++ b/cdp/client/models/fund_quote.py @@ -0,0 +1,114 @@ +# 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 datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List +from cdp.client.models.crypto_amount import CryptoAmount +from cdp.client.models.fiat_amount import FiatAmount +from cdp.client.models.fund_operation_fees import FundOperationFees +from typing import Optional, Set +from typing_extensions import Self + +class FundQuote(BaseModel): + """ + A quote for a fund operation + """ # noqa: E501 + fund_quote_id: StrictStr = Field(description="The ID of the fund quote") + network_id: StrictStr = Field(description="The ID of the blockchain network") + wallet_id: StrictStr = Field(description="The ID of the wallet that will receive the crypto") + address_id: StrictStr = Field(description="The ID of the address that will receive the crypto") + crypto_amount: CryptoAmount + fiat_amount: FiatAmount + expires_at: datetime = Field(description="The time at which the quote expires") + fees: FundOperationFees + __properties: ClassVar[List[str]] = ["fund_quote_id", "network_id", "wallet_id", "address_id", "crypto_amount", "fiat_amount", "expires_at", "fees"] + + 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 FundQuote 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, + ) + # override the default output from pydantic by calling `to_dict()` of crypto_amount + if self.crypto_amount: + _dict['crypto_amount'] = self.crypto_amount.to_dict() + # override the default output from pydantic by calling `to_dict()` of fiat_amount + if self.fiat_amount: + _dict['fiat_amount'] = self.fiat_amount.to_dict() + # override the default output from pydantic by calling `to_dict()` of fees + if self.fees: + _dict['fees'] = self.fees.to_dict() + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of FundQuote from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "fund_quote_id": obj.get("fund_quote_id"), + "network_id": obj.get("network_id"), + "wallet_id": obj.get("wallet_id"), + "address_id": obj.get("address_id"), + "crypto_amount": CryptoAmount.from_dict(obj["crypto_amount"]) if obj.get("crypto_amount") is not None else None, + "fiat_amount": FiatAmount.from_dict(obj["fiat_amount"]) if obj.get("fiat_amount") is not None else None, + "expires_at": obj.get("expires_at"), + "fees": FundOperationFees.from_dict(obj["fees"]) if obj.get("fees") is not None else None + }) + return _obj + + diff --git a/cdp/client/models/onchain_name.py b/cdp/client/models/onchain_name.py index 08b5d4d..c03897a 100644 --- a/cdp/client/models/onchain_name.py +++ b/cdp/client/models/onchain_name.py @@ -17,9 +17,9 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictStr +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr from typing import Any, ClassVar, Dict, List, Optional -from cdp.client.models.onchain_name_text_records_inner import OnchainNameTextRecordsInner from typing import Optional, Set from typing_extensions import Self @@ -34,8 +34,10 @@ class OnchainName(BaseModel): domain: StrictStr = Field(description="The readable format for the name in complete form") avatar: Optional[StrictStr] = Field(default=None, description="The visual representation attached to this name") network_id: StrictStr = Field(description="The ID of the blockchain network") - text_records: Optional[List[OnchainNameTextRecordsInner]] = Field(default=None, description="The metadata attached to this name") - __properties: ClassVar[List[str]] = ["token_id", "owner_address", "manager_address", "primary_address", "domain", "avatar", "network_id", "text_records"] + expires_at: datetime = Field(description="The expiration date for this name's ownership") + text_records: Optional[Dict[str, StrictStr]] = Field(default=None, description="The metadata attached to this name") + is_primary: StrictBool = Field(description="Whether this name is the primary name for the owner (This is when the ETH coin address for this name is equal to the primary_address. More info here https://docs.ens.domains/ensip/19)") + __properties: ClassVar[List[str]] = ["token_id", "owner_address", "manager_address", "primary_address", "domain", "avatar", "network_id", "expires_at", "text_records", "is_primary"] model_config = ConfigDict( populate_by_name=True, @@ -76,13 +78,6 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # override the default output from pydantic by calling `to_dict()` of each item in text_records (list) - _items = [] - if self.text_records: - for _item_text_records in self.text_records: - if _item_text_records: - _items.append(_item_text_records.to_dict()) - _dict['text_records'] = _items return _dict @classmethod @@ -102,7 +97,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "domain": obj.get("domain"), "avatar": obj.get("avatar"), "network_id": obj.get("network_id"), - "text_records": [OnchainNameTextRecordsInner.from_dict(_item) for _item in obj["text_records"]] if obj.get("text_records") is not None else None + "expires_at": obj.get("expires_at"), + "text_records": obj.get("text_records"), + "is_primary": obj.get("is_primary") }) return _obj diff --git a/cdp/faucet_transaction.py b/cdp/faucet_transaction.py index 72b03dc..8fe56ea 100644 --- a/cdp/faucet_transaction.py +++ b/cdp/faucet_transaction.py @@ -1,6 +1,10 @@ +import time + +from cdp.cdp import Cdp from cdp.client.models.faucet_transaction import ( FaucetTransaction as FaucetTransactionModel, ) +from cdp.transaction import Transaction class FaucetTransaction: @@ -15,6 +19,36 @@ def __init__(self, model: FaucetTransactionModel) -> None: """ self._model = model + if self._model.transaction is None: + raise ValueError("Faucet transaction is required.") + + self._transaction = Transaction(self._model.transaction) + + @property + def transaction(self) -> Transaction: + """Get the Faucet transaction.""" + return self._transaction + + @property + def network_id(self) -> str: + """Get the network ID. + + Returns: + str: The network ID. + + """ + return self.transaction.network_id + + @property + def address_id(self) -> str: + """Get the address. + + Returns: + str: The address. + + """ + return self.transaction.to_address_id + @property def transaction_hash(self) -> str: """Get the transaction hash. @@ -23,7 +57,7 @@ def transaction_hash(self) -> str: str: The transaction hash. """ - return self._model.transaction_hash + return self.transaction.transaction_hash @property def transaction_link(self) -> str: @@ -33,11 +67,67 @@ def transaction_link(self) -> str: str: The transaction link. """ - return self._model.transaction_link + return self.transaction.transaction_hash + + @property + def status(self) -> str: + """Get the faucet transaction status. + + Returns: + str: The faucet transaction status. + + """ + return self.transaction.status + + def wait(self, interval_seconds: float = 0.2, timeout_seconds: float = 20) -> "FaucetTransaction": + """Wait for the faucet transaction to complete. + + Args: + interval_seconds (float): The interval seconds. + timeout_seconds (float): The timeout seconds. + + Returns: + FaucetTransaction: The faucet transaction. + + """ + start_time = time.time() + + while not self.transaction.terminal_state: + self.reload() + + if time.time() - start_time > timeout_seconds: + raise TimeoutError("Timed out waiting for FaucetTransaction to land onchain") + + time.sleep(interval_seconds) + + return self + + + def reload(self) -> "FaucetTransaction": + """Reload the faucet transaction. + + Returns: + None + + """ + model = Cdp.api_clients.external_addresses.get_faucet_transaction( + self.network_id, + self.address_id, + self.transaction_hash + ) + self._model = model + + if model.transaction is None: + raise ValueError("Faucet transaction is required.") + + # Update the transaction + self._transaction = Transaction(model.transaction) + + return self def __str__(self) -> str: """Return a string representation of the FaucetTransaction.""" - return f"FaucetTransaction: (transaction_hash: {self.transaction_hash}, transaction_link: {self.transaction_link})" + return f"FaucetTransaction: (transaction_hash: {self.transaction_hash}, transaction_link: {self.transaction_link}, status: {self.status}, network_id: {self.network_id})" def __repr__(self) -> str: """Return a string representation of the FaucetTransaction.""" diff --git a/cdp/transaction.py b/cdp/transaction.py index adab0c7..3f0e451 100644 --- a/cdp/transaction.py +++ b/cdp/transaction.py @@ -104,6 +104,11 @@ def transaction_hash(self) -> str: """Get the transaction hash.""" return self._model.transaction_hash + @property + def network_id(self) -> str: + """Get the Network ID of the Transaction.""" + return self._model.network_id + @property def status(self) -> Status: """Get the status.""" diff --git a/docs/conf.py b/docs/conf.py index 0ef199d..2a89824 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,7 +14,7 @@ project = 'CDP SDK' author = 'Coinbase Developer Platform' -release = '0.0.9' +release = '0.10.0' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/pyproject.toml b/pyproject.toml index 0d01c46..35321fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "cdp-sdk" -version = "0.0.9" +version = "0.10.0" description = "CDP Python SDK" readme = "README.md" authors = [{name = "John Peterson", email = "john.peterson@coinbase.com"}] diff --git a/tests/factories/faucet_transaction_factory.py b/tests/factories/faucet_transaction_factory.py new file mode 100644 index 0000000..fcb2875 --- /dev/null +++ b/tests/factories/faucet_transaction_factory.py @@ -0,0 +1,37 @@ +import pytest + +from cdp.client.models.faucet_transaction import FaucetTransaction as FaucetTransactionModel +from cdp.faucet_transaction import FaucetTransaction + + +@pytest.fixture +def faucet_transaction_model_factory(transaction_model_factory): + """Create and return a factory for creating FaucetTransactionModel fixtures.""" + + def _create_faucet_tx_model(status="complete"): + transaction_model = transaction_model_factory(status) + + if transaction_model.transaction_hash is None: + raise ValueError("Faucet transaction must have a hash.") + + if transaction_model.transaction_link is None: + raise ValueError("Faucet transaction must have a link.") + + return FaucetTransactionModel( + transaction=transaction_model, + transaction_hash=transaction_model.transaction_hash, + transaction_link=transaction_model.transaction_link, + ) + + return _create_faucet_tx_model + + +@pytest.fixture +def faucet_transaction_factory(faucet_transaction_model_factory): + """Create and return a factory for creating FaucetTransaction fixtures.""" + + def _create_faucet_transaction(status="complete"): + faucet_tx_model = faucet_transaction_model_factory(status) + return FaucetTransaction(faucet_tx_model) + + return _create_faucet_transaction diff --git a/tests/factories/transaction_factory.py b/tests/factories/transaction_factory.py index 5fd9712..51ac3a5 100644 --- a/tests/factories/transaction_factory.py +++ b/tests/factories/transaction_factory.py @@ -20,7 +20,7 @@ def _create_transaction_model(status="complete"): else None, status=status, transaction_link="https://sepolia.basescan.org/tx/0xtransactionlink" - if status == "complete" + if status in ["broadcast", "complete"] else None, block_hash="0xblockhash" if status == "complete" else None, block_height="123456" if status == "complete" else None, diff --git a/tests/test_address.py b/tests/test_address.py index c605bd8..a6241f8 100644 --- a/tests/test_address.py +++ b/tests/test_address.py @@ -29,36 +29,42 @@ def test_address_can_sign(address_factory): @patch("cdp.Cdp.api_clients") -def test_address_faucet(mock_api_clients, address_factory): +def test_address_faucet(mock_api_clients, address_factory, faucet_transaction_model_factory): """Test the faucet method of an Address.""" address = address_factory() mock_request_faucet = Mock() - mock_request_faucet.return_value = Mock(spec=FaucetTransaction) + mock_request_faucet.return_value = faucet_transaction_model_factory() mock_api_clients.external_addresses.request_external_faucet_funds = mock_request_faucet faucet_tx = address.faucet() assert isinstance(faucet_tx, FaucetTransaction) mock_request_faucet.assert_called_once_with( - network_id=address.network_id, address_id=address.address_id, asset_id=None + network_id=address.network_id, + address_id=address.address_id, + asset_id=None, + skip_wait=True ) @patch("cdp.Cdp.api_clients") -def test_address_faucet_with_asset_id(mock_api_clients, address_factory): +def test_address_faucet_with_asset_id(mock_api_clients, address_factory, faucet_transaction_model_factory): """Test the faucet method of an Address with an asset_id.""" address = address_factory() mock_request_faucet = Mock() - mock_request_faucet.return_value = Mock(spec=FaucetTransaction) + mock_request_faucet.return_value = faucet_transaction_model_factory() mock_api_clients.external_addresses.request_external_faucet_funds = mock_request_faucet faucet_tx = address.faucet(asset_id="usdc") assert isinstance(faucet_tx, FaucetTransaction) mock_request_faucet.assert_called_once_with( - network_id=address.network_id, address_id=address.address_id, asset_id="usdc" + network_id=address.network_id, + address_id=address.address_id, + asset_id="usdc", + skip_wait=True ) diff --git a/tests/test_faucet_transaction.py b/tests/test_faucet_transaction.py new file mode 100644 index 0000000..341ccab --- /dev/null +++ b/tests/test_faucet_transaction.py @@ -0,0 +1,105 @@ +from unittest.mock import Mock, call, patch + +import pytest + +from cdp.faucet_transaction import FaucetTransaction + + +def test_faucet_tx_initialization(faucet_transaction_factory): + """Test the initialization of a FaucetTransaction.""" + faucet_transaction = faucet_transaction_factory() + + assert isinstance(faucet_transaction, FaucetTransaction) + assert faucet_transaction.transaction_hash == "0xtransactionhash" + assert faucet_transaction.network_id == "base-sepolia" + assert faucet_transaction.address_id == "0xdestination" + assert faucet_transaction.status.value == "complete" + +@patch("cdp.Cdp.api_clients") +def test_reload_faucet_tx(mock_api_clients, faucet_transaction_factory): + """Test the reloading of a FaucetTransaction object.""" + faucet_tx = faucet_transaction_factory(status="broadcast") + complete_faucet_tx = faucet_transaction_factory(status="complete") + + # Mock the GetFaucetTransaction API returning a complete faucet transaction. + mock_get_faucet_tx = Mock() + mock_get_faucet_tx.return_value = complete_faucet_tx._model + mock_api_clients.external_addresses.get_faucet_transaction = mock_get_faucet_tx + + reloaded_faucet_tx = faucet_tx.reload() + + mock_get_faucet_tx.assert_called_once_with( + "base-sepolia", + "0xdestination", + "0xtransactionhash" + ) + assert faucet_tx.status.value == "complete" + assert reloaded_faucet_tx.status.value == "complete" + + +@patch("cdp.Cdp.api_clients") +@patch("cdp.faucet_transaction.time.sleep") +@patch("cdp.faucet_transaction.time.time") +def test_wait_for_faucet_transaction( + mock_time, + mock_sleep, + mock_api_clients, + faucet_transaction_factory +): + """Test the waiting for a FaucetTransaction object to complete.""" + faucet_tx = faucet_transaction_factory(status="broadcast") + complete_faucet_tx = faucet_transaction_factory(status="complete") + + # Mock GetFaucetTransaction returning a `broadcast` and then a `complete` + # faucet transaction. + mock_get_faucet_tx = Mock() + mock_api_clients.external_addresses.get_faucet_transaction = mock_get_faucet_tx + mock_get_faucet_tx.side_effect = [faucet_tx._model, complete_faucet_tx._model] + + mock_time.side_effect = [0, 0.2, 0.4] + + result = faucet_tx.wait(interval_seconds=0.2, timeout_seconds=1) + + assert result.status.value == "complete" + + mock_get_faucet_tx.assert_called_with( + "base-sepolia", + "0xdestination", + "0xtransactionhash" + ) + assert mock_get_faucet_tx.call_count == 2 + mock_sleep.assert_has_calls([call(0.2)] * 2) + assert mock_time.call_count == 3 + + +@patch("cdp.Cdp.api_clients") +@patch("cdp.faucet_transaction.time.sleep") +@patch("cdp.faucet_transaction.time.time") +def test_wait_for_faucet_transaction_timeout( + mock_time, + mock_sleep, + mock_api_clients, + faucet_transaction_factory +): + """Test the waiting for a FaucetTransaction object to complete with a timeout.""" + faucet_tx = faucet_transaction_factory(status="broadcast") + + mock_get_faucet_tx = Mock() + mock_get_faucet_tx.return_value = faucet_tx._model + mock_api_clients.external_addresses.get_faucet_transaction = mock_get_faucet_tx + + mock_time.side_effect = [0, 0.5, 1.0, 1.5, 2.0, 2.5] + + with pytest.raises(TimeoutError, match="Timed out waiting for FaucetTransaction to land onchain"): + faucet_tx.wait(interval_seconds=0.5, timeout_seconds=2) + + mock_get_faucet_tx.assert_called_with( + "base-sepolia", + "0xdestination", + "0xtransactionhash" + ) + + assert mock_get_faucet_tx.call_count == 5 + mock_sleep.assert_has_calls([call(0.5)] * 4) + assert mock_time.call_count == 6 + diff --git a/tests/test_transaction.py b/tests/test_transaction.py index ea8b58b..bc0fd98 100644 --- a/tests/test_transaction.py +++ b/tests/test_transaction.py @@ -16,6 +16,7 @@ def test_transaction_initialization(transaction_factory): assert isinstance(transaction._model, TransactionModel) assert transaction._raw is None assert transaction._signature == "0xsignedpayload" + assert transaction.network_id == "base-sepolia" def test_transaction_initialization_invalid_model():