Skip to content

Commit 5ae9385

Browse files
V0.19.0 (#108)
* SmartWallet support (#105) * Prepping v0.19.0 (#107)
1 parent 6e4e3bc commit 5ae9385

25 files changed

+1400
-43
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# CDP Python SDK Changelog
22

3+
## Unreleased
4+
5+
## [0.19.0] - 2025-02-21
6+
7+
### Added
8+
- Ability to create a SmartWallet and send a user operation.
9+
310
## [0.18.1] - 2025-02-13
411

512
## Fixed

cdp/__init__.py

+12
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
from cdp.balance_map import BalanceMap
66
from cdp.cdp import Cdp
77
from cdp.contract_invocation import ContractInvocation
8+
from cdp.evm_call_types import EncodedCall, FunctionCall
89
from cdp.external_address import ExternalAddress
910
from cdp.faucet_transaction import FaucetTransaction
1011
from cdp.hash_utils import hash_message, hash_typed_data_message
1112
from cdp.mnemonic_seed_phrase import MnemonicSeedPhrase
13+
from cdp.network import Network, SupportedChainId
1214
from cdp.payload_signature import PayloadSignature
1315
from cdp.smart_contract import SmartContract
16+
from cdp.smart_wallet import SmartWallet, to_smart_wallet
1417
from cdp.sponsored_send import SponsoredSend
1518
from cdp.trade import Trade
1619
from cdp.transaction import Transaction
1720
from cdp.transfer import Transfer
21+
from cdp.user_operation import UserOperation
1822
from cdp.wallet import Wallet
1923
from cdp.wallet_address import WalletAddress
2024
from cdp.wallet_data import WalletData
@@ -40,7 +44,15 @@
4044
"WalletAddress",
4145
"WalletData",
4246
"Webhook",
47+
"to_smart_wallet",
48+
"SmartWallet",
4349
"__version__",
4450
"hash_message",
4551
"hash_typed_data_message",
52+
"Network",
53+
"SupportedChainId",
54+
"EncodedCall",
55+
"FunctionCall",
56+
"UserOperation",
57+
"Network",
4658
]

cdp/__version__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.18.1"
1+
__version__ = "0.19.0"

cdp/api_clients.py

+18
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from cdp.client.api.fund_api import FundApi
99
from cdp.client.api.networks_api import NetworksApi
1010
from cdp.client.api.smart_contracts_api import SmartContractsApi
11+
from cdp.client.api.smart_wallets_api import SmartWalletsApi
1112
from cdp.client.api.trades_api import TradesApi
1213
from cdp.client.api.transaction_history_api import TransactionHistoryApi
1314
from cdp.client.api.transfers_api import TransfersApi
@@ -24,6 +25,7 @@ class ApiClients:
2425
Attributes:
2526
_cdp_client (CdpApiClient): The CDP API client used to initialize individual API clients.
2627
_wallets (Optional[WalletsApi]): The WalletsApi client instance.
28+
_smart_wallets (Optional[SmartWalletsApi]): The SmartWalletsApi client instance.
2729
_webhooks (Optional[WebhooksApi]): The WebhooksApi client instance.
2830
_addresses (Optional[AddressesApi]): The AddressesApi client instance.
2931
_external_addresses (Optional[ExternalAddressesApi]): The ExternalAddressesApi client instance.
@@ -44,6 +46,7 @@ def __init__(self, cdp_client: CdpApiClient) -> None:
4446
"""
4547
self._cdp_client: CdpApiClient = cdp_client
4648
self._wallets: WalletsApi | None = None
49+
self._smart_wallets: SmartWalletsApi | None = None
4750
self._webhooks: WebhooksApi | None = None
4851
self._addresses: AddressesApi | None = None
4952
self._external_addresses: ExternalAddressesApi | None = None
@@ -73,6 +76,21 @@ def wallets(self) -> WalletsApi:
7376
self._wallets = WalletsApi(api_client=self._cdp_client)
7477
return self._wallets
7578

79+
@property
80+
def smart_wallets(self) -> SmartWalletsApi:
81+
"""Get the SmartWalletsApi client instance.
82+
83+
Returns:
84+
SmartWalletsApi: The SmartWalletsApi client instance.
85+
86+
Note:
87+
This property lazily initializes the SmartWalletsApi client on first access.
88+
89+
"""
90+
if self._smart_wallets is None:
91+
self._smart_wallets = SmartWalletsApi(api_client=self._cdp_client)
92+
return self._smart_wallets
93+
7694
@property
7795
def webhooks(self) -> WebhooksApi:
7896
"""Get the WebhooksApi client instance.

cdp/client/api/smart_wallets_api.py

+32-32
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def __init__(self, api_client=None) -> None:
4848
def broadcast_user_operation(
4949
self,
5050
smart_wallet_address: Annotated[StrictStr, Field(description="The address of the smart wallet to broadcast the user operation from.")],
51-
user_operation_id: Annotated[StrictStr, Field(description="The ID of the user operation to broadcast.")],
51+
user_op_hash: Annotated[StrictStr, Field(description="The hash of the user operation to broadcast")],
5252
broadcast_user_operation_request: Optional[BroadcastUserOperationRequest] = None,
5353
_request_timeout: Union[
5454
None,
@@ -69,8 +69,8 @@ def broadcast_user_operation(
6969
7070
:param smart_wallet_address: The address of the smart wallet to broadcast the user operation from. (required)
7171
:type smart_wallet_address: str
72-
:param user_operation_id: The ID of the user operation to broadcast. (required)
73-
:type user_operation_id: str
72+
:param user_op_hash: The hash of the user operation to broadcast (required)
73+
:type user_op_hash: str
7474
:param broadcast_user_operation_request:
7575
:type broadcast_user_operation_request: BroadcastUserOperationRequest
7676
:param _request_timeout: timeout setting for this request. If one
@@ -97,7 +97,7 @@ def broadcast_user_operation(
9797

9898
_param = self._broadcast_user_operation_serialize(
9999
smart_wallet_address=smart_wallet_address,
100-
user_operation_id=user_operation_id,
100+
user_op_hash=user_op_hash,
101101
broadcast_user_operation_request=broadcast_user_operation_request,
102102
_request_auth=_request_auth,
103103
_content_type=_content_type,
@@ -123,7 +123,7 @@ def broadcast_user_operation(
123123
def broadcast_user_operation_with_http_info(
124124
self,
125125
smart_wallet_address: Annotated[StrictStr, Field(description="The address of the smart wallet to broadcast the user operation from.")],
126-
user_operation_id: Annotated[StrictStr, Field(description="The ID of the user operation to broadcast.")],
126+
user_op_hash: Annotated[StrictStr, Field(description="The hash of the user operation to broadcast")],
127127
broadcast_user_operation_request: Optional[BroadcastUserOperationRequest] = None,
128128
_request_timeout: Union[
129129
None,
@@ -144,8 +144,8 @@ def broadcast_user_operation_with_http_info(
144144
145145
:param smart_wallet_address: The address of the smart wallet to broadcast the user operation from. (required)
146146
:type smart_wallet_address: str
147-
:param user_operation_id: The ID of the user operation to broadcast. (required)
148-
:type user_operation_id: str
147+
:param user_op_hash: The hash of the user operation to broadcast (required)
148+
:type user_op_hash: str
149149
:param broadcast_user_operation_request:
150150
:type broadcast_user_operation_request: BroadcastUserOperationRequest
151151
:param _request_timeout: timeout setting for this request. If one
@@ -172,7 +172,7 @@ def broadcast_user_operation_with_http_info(
172172

173173
_param = self._broadcast_user_operation_serialize(
174174
smart_wallet_address=smart_wallet_address,
175-
user_operation_id=user_operation_id,
175+
user_op_hash=user_op_hash,
176176
broadcast_user_operation_request=broadcast_user_operation_request,
177177
_request_auth=_request_auth,
178178
_content_type=_content_type,
@@ -198,7 +198,7 @@ def broadcast_user_operation_with_http_info(
198198
def broadcast_user_operation_without_preload_content(
199199
self,
200200
smart_wallet_address: Annotated[StrictStr, Field(description="The address of the smart wallet to broadcast the user operation from.")],
201-
user_operation_id: Annotated[StrictStr, Field(description="The ID of the user operation to broadcast.")],
201+
user_op_hash: Annotated[StrictStr, Field(description="The hash of the user operation to broadcast")],
202202
broadcast_user_operation_request: Optional[BroadcastUserOperationRequest] = None,
203203
_request_timeout: Union[
204204
None,
@@ -219,8 +219,8 @@ def broadcast_user_operation_without_preload_content(
219219
220220
:param smart_wallet_address: The address of the smart wallet to broadcast the user operation from. (required)
221221
:type smart_wallet_address: str
222-
:param user_operation_id: The ID of the user operation to broadcast. (required)
223-
:type user_operation_id: str
222+
:param user_op_hash: The hash of the user operation to broadcast (required)
223+
:type user_op_hash: str
224224
:param broadcast_user_operation_request:
225225
:type broadcast_user_operation_request: BroadcastUserOperationRequest
226226
:param _request_timeout: timeout setting for this request. If one
@@ -247,7 +247,7 @@ def broadcast_user_operation_without_preload_content(
247247

248248
_param = self._broadcast_user_operation_serialize(
249249
smart_wallet_address=smart_wallet_address,
250-
user_operation_id=user_operation_id,
250+
user_op_hash=user_op_hash,
251251
broadcast_user_operation_request=broadcast_user_operation_request,
252252
_request_auth=_request_auth,
253253
_content_type=_content_type,
@@ -268,7 +268,7 @@ def broadcast_user_operation_without_preload_content(
268268
def _broadcast_user_operation_serialize(
269269
self,
270270
smart_wallet_address,
271-
user_operation_id,
271+
user_op_hash,
272272
broadcast_user_operation_request,
273273
_request_auth,
274274
_content_type,
@@ -293,8 +293,8 @@ def _broadcast_user_operation_serialize(
293293
# process the path parameters
294294
if smart_wallet_address is not None:
295295
_path_params['smart_wallet_address'] = smart_wallet_address
296-
if user_operation_id is not None:
297-
_path_params['user_operation_id'] = user_operation_id
296+
if user_op_hash is not None:
297+
_path_params['user_op_hash'] = user_op_hash
298298
# process the query parameters
299299
# process the header parameters
300300
# process the form parameters
@@ -332,7 +332,7 @@ def _broadcast_user_operation_serialize(
332332

333333
return self.api_client.param_serialize(
334334
method='POST',
335-
resource_path='/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_operation_id}/broadcast',
335+
resource_path='/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_op_hash}/broadcast',
336336
path_params=_path_params,
337337
query_params=_query_params,
338338
header_params=_header_params,
@@ -1192,7 +1192,7 @@ def _get_smart_wallet_serialize(
11921192
def get_user_operation(
11931193
self,
11941194
smart_wallet_address: Annotated[StrictStr, Field(description="The address of the smart wallet the user operation belongs to.")],
1195-
user_operation_id: Annotated[StrictStr, Field(description="The ID of the user operation to fetch.")],
1195+
user_op_hash: Annotated[StrictStr, Field(description="The hash of the user operation to fetch")],
11961196
_request_timeout: Union[
11971197
None,
11981198
Annotated[StrictFloat, Field(gt=0)],
@@ -1212,8 +1212,8 @@ def get_user_operation(
12121212
12131213
:param smart_wallet_address: The address of the smart wallet the user operation belongs to. (required)
12141214
:type smart_wallet_address: str
1215-
:param user_operation_id: The ID of the user operation to fetch. (required)
1216-
:type user_operation_id: str
1215+
:param user_op_hash: The hash of the user operation to fetch (required)
1216+
:type user_op_hash: str
12171217
:param _request_timeout: timeout setting for this request. If one
12181218
number provided, it will be total request
12191219
timeout. It can also be a pair (tuple) of
@@ -1238,7 +1238,7 @@ def get_user_operation(
12381238

12391239
_param = self._get_user_operation_serialize(
12401240
smart_wallet_address=smart_wallet_address,
1241-
user_operation_id=user_operation_id,
1241+
user_op_hash=user_op_hash,
12421242
_request_auth=_request_auth,
12431243
_content_type=_content_type,
12441244
_headers=_headers,
@@ -1263,7 +1263,7 @@ def get_user_operation(
12631263
def get_user_operation_with_http_info(
12641264
self,
12651265
smart_wallet_address: Annotated[StrictStr, Field(description="The address of the smart wallet the user operation belongs to.")],
1266-
user_operation_id: Annotated[StrictStr, Field(description="The ID of the user operation to fetch.")],
1266+
user_op_hash: Annotated[StrictStr, Field(description="The hash of the user operation to fetch")],
12671267
_request_timeout: Union[
12681268
None,
12691269
Annotated[StrictFloat, Field(gt=0)],
@@ -1283,8 +1283,8 @@ def get_user_operation_with_http_info(
12831283
12841284
:param smart_wallet_address: The address of the smart wallet the user operation belongs to. (required)
12851285
:type smart_wallet_address: str
1286-
:param user_operation_id: The ID of the user operation to fetch. (required)
1287-
:type user_operation_id: str
1286+
:param user_op_hash: The hash of the user operation to fetch (required)
1287+
:type user_op_hash: str
12881288
:param _request_timeout: timeout setting for this request. If one
12891289
number provided, it will be total request
12901290
timeout. It can also be a pair (tuple) of
@@ -1309,7 +1309,7 @@ def get_user_operation_with_http_info(
13091309

13101310
_param = self._get_user_operation_serialize(
13111311
smart_wallet_address=smart_wallet_address,
1312-
user_operation_id=user_operation_id,
1312+
user_op_hash=user_op_hash,
13131313
_request_auth=_request_auth,
13141314
_content_type=_content_type,
13151315
_headers=_headers,
@@ -1334,7 +1334,7 @@ def get_user_operation_with_http_info(
13341334
def get_user_operation_without_preload_content(
13351335
self,
13361336
smart_wallet_address: Annotated[StrictStr, Field(description="The address of the smart wallet the user operation belongs to.")],
1337-
user_operation_id: Annotated[StrictStr, Field(description="The ID of the user operation to fetch.")],
1337+
user_op_hash: Annotated[StrictStr, Field(description="The hash of the user operation to fetch")],
13381338
_request_timeout: Union[
13391339
None,
13401340
Annotated[StrictFloat, Field(gt=0)],
@@ -1354,8 +1354,8 @@ def get_user_operation_without_preload_content(
13541354
13551355
:param smart_wallet_address: The address of the smart wallet the user operation belongs to. (required)
13561356
:type smart_wallet_address: str
1357-
:param user_operation_id: The ID of the user operation to fetch. (required)
1358-
:type user_operation_id: str
1357+
:param user_op_hash: The hash of the user operation to fetch (required)
1358+
:type user_op_hash: str
13591359
:param _request_timeout: timeout setting for this request. If one
13601360
number provided, it will be total request
13611361
timeout. It can also be a pair (tuple) of
@@ -1380,7 +1380,7 @@ def get_user_operation_without_preload_content(
13801380

13811381
_param = self._get_user_operation_serialize(
13821382
smart_wallet_address=smart_wallet_address,
1383-
user_operation_id=user_operation_id,
1383+
user_op_hash=user_op_hash,
13841384
_request_auth=_request_auth,
13851385
_content_type=_content_type,
13861386
_headers=_headers,
@@ -1400,7 +1400,7 @@ def get_user_operation_without_preload_content(
14001400
def _get_user_operation_serialize(
14011401
self,
14021402
smart_wallet_address,
1403-
user_operation_id,
1403+
user_op_hash,
14041404
_request_auth,
14051405
_content_type,
14061406
_headers,
@@ -1424,8 +1424,8 @@ def _get_user_operation_serialize(
14241424
# process the path parameters
14251425
if smart_wallet_address is not None:
14261426
_path_params['smart_wallet_address'] = smart_wallet_address
1427-
if user_operation_id is not None:
1428-
_path_params['user_operation_id'] = user_operation_id
1427+
if user_op_hash is not None:
1428+
_path_params['user_op_hash'] = user_op_hash
14291429
# process the query parameters
14301430
# process the header parameters
14311431
# process the form parameters
@@ -1449,7 +1449,7 @@ def _get_user_operation_serialize(
14491449

14501450
return self.api_client.param_serialize(
14511451
method='GET',
1452-
resource_path='/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_operation_id}',
1452+
resource_path='/v1/smart_wallets/{smart_wallet_address}/user_operations/{user_op_hash}',
14531453
path_params=_path_params,
14541454
query_params=_query_params,
14551455
header_params=_header_params,

cdp/client/models/create_user_operation_request.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
import re # noqa: F401
1818
import json
1919

20-
from pydantic import BaseModel, ConfigDict, Field
21-
from typing import Any, ClassVar, Dict, List
20+
from pydantic import BaseModel, ConfigDict, Field, StrictStr
21+
from typing import Any, ClassVar, Dict, List, Optional
2222
from cdp.client.models.call import Call
2323
from typing import Optional, Set
2424
from typing_extensions import Self
@@ -28,7 +28,8 @@ class CreateUserOperationRequest(BaseModel):
2828
CreateUserOperationRequest
2929
""" # noqa: E501
3030
calls: List[Call] = Field(description="The list of calls to make from the smart wallet.")
31-
__properties: ClassVar[List[str]] = ["calls"]
31+
paymaster_url: Optional[StrictStr] = Field(default=None, description="The URL of the paymaster to use for the user operation.")
32+
__properties: ClassVar[List[str]] = ["calls", "paymaster_url"]
3233

3334
model_config = ConfigDict(
3435
populate_by_name=True,
@@ -88,7 +89,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
8889
return cls.model_validate(obj)
8990

9091
_obj = cls.model_validate({
91-
"calls": [Call.from_dict(_item) for _item in obj["calls"]] if obj.get("calls") is not None else None
92+
"calls": [Call.from_dict(_item) for _item in obj["calls"]] if obj.get("calls") is not None else None,
93+
"paymaster_url": obj.get("paymaster_url")
9294
})
9395
return _obj
9496

cdp/client/models/user_operation.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ class UserOperation(BaseModel):
3030
id: StrictStr = Field(description="The ID of the user operation.")
3131
network_id: StrictStr = Field(description="The ID of the network the user operation is being created on.")
3232
calls: List[Call] = Field(description="The list of calls to make from the smart wallet.")
33+
user_op_hash: StrictStr = Field(description="The unique identifier for the user operation onchain. This is the payload that must be signed by one of the owners of the smart wallet to send the user operation.")
3334
unsigned_payload: StrictStr = Field(description="The hex-encoded hash that must be signed by the user.")
3435
signature: Optional[StrictStr] = Field(default=None, description="The hex-encoded signature of the user operation.")
3536
transaction_hash: Optional[StrictStr] = Field(default=None, description="The hash of the transaction that was broadcast.")
3637
status: StrictStr = Field(description="The status of the user operation.")
37-
__properties: ClassVar[List[str]] = ["id", "network_id", "calls", "unsigned_payload", "signature", "transaction_hash", "status"]
38+
__properties: ClassVar[List[str]] = ["id", "network_id", "calls", "user_op_hash", "unsigned_payload", "signature", "transaction_hash", "status"]
3839

3940
@field_validator('status')
4041
def status_validate_enum(cls, value):
@@ -104,6 +105,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
104105
"id": obj.get("id"),
105106
"network_id": obj.get("network_id"),
106107
"calls": [Call.from_dict(_item) for _item in obj["calls"]] if obj.get("calls") is not None else None,
108+
"user_op_hash": obj.get("user_op_hash"),
107109
"unsigned_payload": obj.get("unsigned_payload"),
108110
"signature": obj.get("signature"),
109111
"transaction_hash": obj.get("transaction_hash"),

0 commit comments

Comments
 (0)