chipi-stack 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chipi_sdk/__init__.py +342 -0
- chipi_sdk/client.py +505 -0
- chipi_sdk/constants.py +171 -0
- chipi_sdk/encryption.py +179 -0
- chipi_sdk/errors.py +130 -0
- chipi_sdk/execute_paymaster.py +434 -0
- chipi_sdk/formatters.py +154 -0
- chipi_sdk/models/__init__.py +145 -0
- chipi_sdk/models/core.py +96 -0
- chipi_sdk/models/session.py +119 -0
- chipi_sdk/models/sku.py +28 -0
- chipi_sdk/models/sku_transaction.py +30 -0
- chipi_sdk/models/transaction.py +192 -0
- chipi_sdk/models/user.py +31 -0
- chipi_sdk/models/wallet.py +178 -0
- chipi_sdk/models/x402.py +117 -0
- chipi_sdk/py.typed +1 -0
- chipi_sdk/sdk.py +1021 -0
- chipi_sdk/sessions.py +836 -0
- chipi_sdk/sku_transactions.py +58 -0
- chipi_sdk/skus.py +93 -0
- chipi_sdk/transactions.py +447 -0
- chipi_sdk/users.py +92 -0
- chipi_sdk/validators.py +75 -0
- chipi_sdk/wallets.py +465 -0
- chipi_sdk/x402_client.py +207 -0
- chipi_sdk/x402_facilitator.py +200 -0
- chipi_sdk/x402_middleware.py +280 -0
- chipi_stack-2.0.0.dist-info/METADATA +366 -0
- chipi_stack-2.0.0.dist-info/RECORD +33 -0
- chipi_stack-2.0.0.dist-info/WHEEL +5 -0
- chipi_stack-2.0.0.dist-info/licenses/LICENSE +21 -0
- chipi_stack-2.0.0.dist-info/top_level.txt +1 -0
chipi_sdk/validators.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Validation utilities for Chipi SDK."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def is_valid_api_key(api_key: str) -> bool:
|
|
8
|
+
"""
|
|
9
|
+
Validate API key format.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
api_key: API key string to validate
|
|
13
|
+
|
|
14
|
+
Returns:
|
|
15
|
+
True if valid, False otherwise
|
|
16
|
+
"""
|
|
17
|
+
if not api_key or not isinstance(api_key, str):
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
# API keys should be non-empty strings with reasonable length
|
|
21
|
+
return len(api_key) > 0 and len(api_key) < 500
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def validate_address(address: str) -> bool:
|
|
25
|
+
"""
|
|
26
|
+
Validate Starknet address format.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
address: Starknet address to validate
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
True if valid, False otherwise
|
|
33
|
+
"""
|
|
34
|
+
if not address or not isinstance(address, str):
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
# Starknet addresses should start with 0x and be hex
|
|
38
|
+
if not address.startswith("0x"):
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
# Remove 0x prefix and validate hex
|
|
42
|
+
hex_part = address[2:]
|
|
43
|
+
if not hex_part:
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
# Check if it's valid hex (0-9, a-f, A-F)
|
|
47
|
+
return bool(re.match(r"^[0-9a-fA-F]+$", hex_part))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def validate_error_response(response: dict[str, Any]) -> dict[str, Any]:
|
|
51
|
+
"""
|
|
52
|
+
Validate and normalize error response.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
response: Error response dictionary
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Normalized error response with message and code
|
|
59
|
+
"""
|
|
60
|
+
if not isinstance(response, dict):
|
|
61
|
+
return {
|
|
62
|
+
"message": "Unknown error occurred",
|
|
63
|
+
"code": "UNKNOWN_ERROR",
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
message = response.get("message")
|
|
67
|
+
if not message:
|
|
68
|
+
message = response.get("error", "Unknown error occurred")
|
|
69
|
+
|
|
70
|
+
code = response.get("code", "UNKNOWN_ERROR")
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
"message": str(message),
|
|
74
|
+
"code": str(code),
|
|
75
|
+
}
|
chipi_sdk/wallets.py
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
"""Wallet management utilities."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import secrets
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from starknet_py.net.full_node_client import FullNodeClient
|
|
7
|
+
from starknet_py.net.account.account import Account
|
|
8
|
+
from starknet_py.net.models import StarknetChainId
|
|
9
|
+
from starknet_py.hash.address import compute_address
|
|
10
|
+
from starknet_py.hash.selector import get_selector_from_name
|
|
11
|
+
from starknet_py.cairo.felt import encode_shortstring
|
|
12
|
+
|
|
13
|
+
from .models.wallet import (
|
|
14
|
+
CreateWalletParams,
|
|
15
|
+
CreateWalletResponse,
|
|
16
|
+
GetWalletParams,
|
|
17
|
+
GetWalletResponse,
|
|
18
|
+
GetTokenBalanceParams,
|
|
19
|
+
GetTokenBalanceResponse,
|
|
20
|
+
WalletType,
|
|
21
|
+
WalletData,
|
|
22
|
+
DeploymentData,
|
|
23
|
+
CreateCustodialWalletParams,
|
|
24
|
+
PrepareWalletUpgradeParams,
|
|
25
|
+
PrepareWalletUpgradeResponse,
|
|
26
|
+
ExecuteWalletUpgradeParams,
|
|
27
|
+
ExecuteWalletUpgradeResponse,
|
|
28
|
+
)
|
|
29
|
+
from .encryption import encrypt_private_key
|
|
30
|
+
from .errors import ChipiTransactionError, ChipiApiError
|
|
31
|
+
from .constants import (
|
|
32
|
+
API_ENDPOINTS,
|
|
33
|
+
WALLET_CLASS_HASHES,
|
|
34
|
+
WALLET_RPC_ENDPOINTS,
|
|
35
|
+
)
|
|
36
|
+
from .client import ChipiClient
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ChipiWallets:
|
|
40
|
+
"""Wallet management class."""
|
|
41
|
+
|
|
42
|
+
def __init__(self, client: ChipiClient):
|
|
43
|
+
"""
|
|
44
|
+
Initialize wallet manager.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
client: Chipi HTTP client
|
|
48
|
+
"""
|
|
49
|
+
self.client = client
|
|
50
|
+
|
|
51
|
+
def _get_private_key(self) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Generate a random private key compatible with Starknet.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Private key as hex string with 0x prefix
|
|
57
|
+
"""
|
|
58
|
+
# Generate 32 random bytes (256 bits)
|
|
59
|
+
private_key_bytes = secrets.token_bytes(32)
|
|
60
|
+
private_key = private_key_bytes.hex()
|
|
61
|
+
full_private_key = f"0x{private_key}"
|
|
62
|
+
|
|
63
|
+
# Ensure the private key is within Starknet's valid range (0 to 2^251 - 1)
|
|
64
|
+
max_starknet_value = 2**251
|
|
65
|
+
private_key_int = int(full_private_key, 16) % max_starknet_value
|
|
66
|
+
|
|
67
|
+
# Convert back to hex string with '0x' prefix
|
|
68
|
+
return f"0x{private_key_int:064x}"
|
|
69
|
+
|
|
70
|
+
def _build_constructor_calldata(
|
|
71
|
+
self, wallet_type: WalletType, stark_key_pub: str
|
|
72
|
+
) -> list[int]:
|
|
73
|
+
"""
|
|
74
|
+
Build constructor calldata based on wallet type.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
wallet_type: Type of wallet (CHIPI or READY)
|
|
78
|
+
stark_key_pub: Public key
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
List of calldata values as integers
|
|
82
|
+
"""
|
|
83
|
+
if wallet_type == WalletType.READY:
|
|
84
|
+
# Argent X Account: owner (CairoCustomEnum) + guardian (CairoOption None)
|
|
85
|
+
# This is a simplified version - full Cairo enum encoding needed
|
|
86
|
+
# For now, return basic structure
|
|
87
|
+
return [int(stark_key_pub, 16), 0] # owner pubkey, no guardian
|
|
88
|
+
|
|
89
|
+
# CHIPI wallet: Simple OpenZeppelin account with just public_key
|
|
90
|
+
return [int(stark_key_pub, 16)]
|
|
91
|
+
|
|
92
|
+
async def acreate_wallet(
|
|
93
|
+
self, params: CreateWalletParams, bearer_token: str
|
|
94
|
+
) -> CreateWalletResponse:
|
|
95
|
+
"""
|
|
96
|
+
Create a new wallet (async).
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
params: Wallet creation parameters
|
|
100
|
+
bearer_token: Authentication token
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Wallet creation response with transaction hash and wallet data
|
|
104
|
+
|
|
105
|
+
Raises:
|
|
106
|
+
ChipiTransactionError: If wallet creation fails
|
|
107
|
+
"""
|
|
108
|
+
try:
|
|
109
|
+
encrypt_key = params.encrypt_key
|
|
110
|
+
external_user_id = params.external_user_id
|
|
111
|
+
user_id = params.user_id
|
|
112
|
+
wallet_type = params.wallet_type or WalletType.CHIPI
|
|
113
|
+
use_passkey = params.use_passkey or False
|
|
114
|
+
|
|
115
|
+
if not encrypt_key:
|
|
116
|
+
error_msg = (
|
|
117
|
+
"encryptKey is required when using passkey. The passkey authentication should have provided the encryptKey."
|
|
118
|
+
if use_passkey
|
|
119
|
+
else "encryptKey is required for wallet creation"
|
|
120
|
+
)
|
|
121
|
+
raise ValueError(error_msg)
|
|
122
|
+
|
|
123
|
+
# Select RPC endpoint based on wallet type
|
|
124
|
+
rpc_url = WALLET_RPC_ENDPOINTS.get(
|
|
125
|
+
wallet_type, WALLET_RPC_ENDPOINTS[WalletType.CHIPI]
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
provider = FullNodeClient(node_url=rpc_url)
|
|
129
|
+
|
|
130
|
+
# Generate private key
|
|
131
|
+
private_key_ax = self._get_private_key()
|
|
132
|
+
|
|
133
|
+
# Get public key from private key
|
|
134
|
+
from starknet_py.net.signer.stark_curve_signer import KeyPair
|
|
135
|
+
key_pair = KeyPair.from_private_key(int(private_key_ax, 16))
|
|
136
|
+
stark_key_pub_ax = hex(key_pair.public_key)
|
|
137
|
+
|
|
138
|
+
# Select class hash based on wallet type
|
|
139
|
+
account_class_hash = WALLET_CLASS_HASHES.get(
|
|
140
|
+
wallet_type, WALLET_CLASS_HASHES[WalletType.CHIPI]
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Build constructor calldata
|
|
144
|
+
constructor_calldata = self._build_constructor_calldata(
|
|
145
|
+
wallet_type, stark_key_pub_ax
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Calculate future address of the account
|
|
149
|
+
public_key = compute_address(
|
|
150
|
+
salt=int(stark_key_pub_ax, 16),
|
|
151
|
+
class_hash=int(account_class_hash, 16),
|
|
152
|
+
constructor_calldata=constructor_calldata,
|
|
153
|
+
deployer_address=0,
|
|
154
|
+
)
|
|
155
|
+
public_key_hex = hex(public_key)
|
|
156
|
+
|
|
157
|
+
# Create account instance
|
|
158
|
+
account = Account(
|
|
159
|
+
client=provider,
|
|
160
|
+
address=public_key_hex,
|
|
161
|
+
key_pair=key_pair,
|
|
162
|
+
chain=StarknetChainId.MAINNET,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Prepare wallet creation via API
|
|
166
|
+
typed_data_response = await self.client.apost(
|
|
167
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/prepare-creation",
|
|
168
|
+
bearer_token=bearer_token,
|
|
169
|
+
body={
|
|
170
|
+
"publicKey": public_key_hex,
|
|
171
|
+
"walletType": wallet_type.value,
|
|
172
|
+
"starkKeyPubAX": stark_key_pub_ax,
|
|
173
|
+
},
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
typed_data = typed_data_response["typedData"]
|
|
177
|
+
account_class_hash_response = typed_data_response["accountClassHash"]
|
|
178
|
+
|
|
179
|
+
# Sign the typed data
|
|
180
|
+
user_signature = account.sign_message(typed_data)
|
|
181
|
+
|
|
182
|
+
# Prepare deployment data
|
|
183
|
+
deployment_data = {
|
|
184
|
+
"class_hash": account_class_hash_response,
|
|
185
|
+
"salt": stark_key_pub_ax,
|
|
186
|
+
"unique": hex(0),
|
|
187
|
+
"calldata": [hex(val) for val in constructor_calldata],
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
# Encrypt private key
|
|
191
|
+
encrypted_private_key = encrypt_private_key(private_key_ax, encrypt_key)
|
|
192
|
+
|
|
193
|
+
# Create wallet via API
|
|
194
|
+
response = await self.client.apost(
|
|
195
|
+
endpoint=API_ENDPOINTS["CHIPI_WALLETS"],
|
|
196
|
+
bearer_token=bearer_token,
|
|
197
|
+
body={
|
|
198
|
+
"externalUserId": external_user_id,
|
|
199
|
+
"userId": user_id,
|
|
200
|
+
"publicKey": public_key_hex,
|
|
201
|
+
"walletType": wallet_type.value,
|
|
202
|
+
"userSignature": {
|
|
203
|
+
"r": str(user_signature[0]),
|
|
204
|
+
"s": str(user_signature[1]),
|
|
205
|
+
"recovery": 0,
|
|
206
|
+
},
|
|
207
|
+
"typedData": typed_data,
|
|
208
|
+
"encryptedPrivateKey": encrypted_private_key,
|
|
209
|
+
"deploymentData": deployment_data,
|
|
210
|
+
},
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return CreateWalletResponse(**response)
|
|
214
|
+
except Exception as error:
|
|
215
|
+
print(f"Detailed error: {error}")
|
|
216
|
+
raise ChipiTransactionError(
|
|
217
|
+
f"Failed to create wallet: {str(error)}", "WALLET_CREATION_FAILED"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
def create_wallet(
|
|
221
|
+
self, params: CreateWalletParams, bearer_token: str
|
|
222
|
+
) -> CreateWalletResponse:
|
|
223
|
+
"""
|
|
224
|
+
Create a new wallet (sync).
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
params: Wallet creation parameters
|
|
228
|
+
bearer_token: Authentication token
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
Wallet creation response
|
|
232
|
+
|
|
233
|
+
Raises:
|
|
234
|
+
ChipiTransactionError: If wallet creation fails
|
|
235
|
+
"""
|
|
236
|
+
# Sync version - simplified, users should prefer async
|
|
237
|
+
import asyncio
|
|
238
|
+
return asyncio.run(self.acreate_wallet(params, bearer_token))
|
|
239
|
+
|
|
240
|
+
async def aget_wallet(
|
|
241
|
+
self, params: GetWalletParams, bearer_token: str
|
|
242
|
+
) -> Optional[GetWalletResponse]:
|
|
243
|
+
"""
|
|
244
|
+
Retrieve a wallet by external user ID (async).
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
params: Wallet query parameters
|
|
248
|
+
bearer_token: Authentication token
|
|
249
|
+
|
|
250
|
+
Returns:
|
|
251
|
+
Wallet data or None if not found
|
|
252
|
+
|
|
253
|
+
Raises:
|
|
254
|
+
ChipiApiError: If request fails (except 404)
|
|
255
|
+
"""
|
|
256
|
+
try:
|
|
257
|
+
response = await self.client.aget(
|
|
258
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/by-user",
|
|
259
|
+
params={"externalUserId": params.external_user_id},
|
|
260
|
+
bearer_token=bearer_token,
|
|
261
|
+
)
|
|
262
|
+
return GetWalletResponse(**response)
|
|
263
|
+
except ChipiApiError as err:
|
|
264
|
+
if err.status == 404:
|
|
265
|
+
return None
|
|
266
|
+
raise
|
|
267
|
+
|
|
268
|
+
def get_wallet(
|
|
269
|
+
self, params: GetWalletParams, bearer_token: str
|
|
270
|
+
) -> Optional[GetWalletResponse]:
|
|
271
|
+
"""
|
|
272
|
+
Retrieve a wallet by external user ID (sync).
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
params: Wallet query parameters
|
|
276
|
+
bearer_token: Authentication token
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
Wallet data or None if not found
|
|
280
|
+
"""
|
|
281
|
+
try:
|
|
282
|
+
response = self.client.get(
|
|
283
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/by-user",
|
|
284
|
+
params={"externalUserId": params.external_user_id},
|
|
285
|
+
bearer_token=bearer_token,
|
|
286
|
+
)
|
|
287
|
+
return GetWalletResponse(**response)
|
|
288
|
+
except ChipiApiError as err:
|
|
289
|
+
if err.status == 404:
|
|
290
|
+
return None
|
|
291
|
+
raise
|
|
292
|
+
|
|
293
|
+
async def aget_token_balance(
|
|
294
|
+
self, params: GetTokenBalanceParams, bearer_token: str
|
|
295
|
+
) -> GetTokenBalanceResponse:
|
|
296
|
+
"""
|
|
297
|
+
Query token balance (async).
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
params: Balance query parameters
|
|
301
|
+
bearer_token: Authentication token
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
Token balance information
|
|
305
|
+
"""
|
|
306
|
+
response = await self.client.aget(
|
|
307
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/token-balance",
|
|
308
|
+
params=params.model_dump(by_alias=True, exclude_none=True),
|
|
309
|
+
bearer_token=bearer_token,
|
|
310
|
+
)
|
|
311
|
+
return GetTokenBalanceResponse(**response)
|
|
312
|
+
|
|
313
|
+
def get_token_balance(
|
|
314
|
+
self, params: GetTokenBalanceParams, bearer_token: str
|
|
315
|
+
) -> GetTokenBalanceResponse:
|
|
316
|
+
"""
|
|
317
|
+
Query token balance (sync).
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
params: Balance query parameters
|
|
321
|
+
bearer_token: Authentication token
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
Token balance information
|
|
325
|
+
"""
|
|
326
|
+
response = self.client.get(
|
|
327
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/token-balance",
|
|
328
|
+
params=params.model_dump(by_alias=True, exclude_none=True),
|
|
329
|
+
bearer_token=bearer_token,
|
|
330
|
+
)
|
|
331
|
+
return GetTokenBalanceResponse(**response)
|
|
332
|
+
|
|
333
|
+
async def acreate_custodial_wallet(
|
|
334
|
+
self, params: CreateCustodialWalletParams, bearer_token: str
|
|
335
|
+
) -> WalletData:
|
|
336
|
+
"""
|
|
337
|
+
Create a custodial merchant wallet (async).
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
params: Custodial wallet parameters
|
|
341
|
+
bearer_token: Authentication token
|
|
342
|
+
|
|
343
|
+
Returns:
|
|
344
|
+
Wallet data
|
|
345
|
+
"""
|
|
346
|
+
response = await self.client.apost(
|
|
347
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/custodial",
|
|
348
|
+
bearer_token=bearer_token,
|
|
349
|
+
body=params.model_dump(),
|
|
350
|
+
)
|
|
351
|
+
return WalletData(**response)
|
|
352
|
+
|
|
353
|
+
def create_custodial_wallet(
|
|
354
|
+
self, params: CreateCustodialWalletParams, bearer_token: str
|
|
355
|
+
) -> WalletData:
|
|
356
|
+
"""
|
|
357
|
+
Create a custodial merchant wallet (sync).
|
|
358
|
+
|
|
359
|
+
Args:
|
|
360
|
+
params: Custodial wallet parameters
|
|
361
|
+
bearer_token: Authentication token
|
|
362
|
+
|
|
363
|
+
Returns:
|
|
364
|
+
Wallet data
|
|
365
|
+
"""
|
|
366
|
+
response = self.client.post(
|
|
367
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/custodial",
|
|
368
|
+
bearer_token=bearer_token,
|
|
369
|
+
body=params.model_dump(),
|
|
370
|
+
)
|
|
371
|
+
return WalletData(**response)
|
|
372
|
+
|
|
373
|
+
async def aprepare_wallet_upgrade(
|
|
374
|
+
self, params: PrepareWalletUpgradeParams, bearer_token: str
|
|
375
|
+
) -> PrepareWalletUpgradeResponse:
|
|
376
|
+
"""
|
|
377
|
+
Prepare a wallet upgrade (async).
|
|
378
|
+
|
|
379
|
+
Args:
|
|
380
|
+
params: Upgrade preparation parameters
|
|
381
|
+
bearer_token: Authentication token
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
Typed data to sign for the upgrade
|
|
385
|
+
"""
|
|
386
|
+
body = {"walletAddress": params.wallet_address}
|
|
387
|
+
if params.target_class_hash:
|
|
388
|
+
body["targetClassHash"] = params.target_class_hash
|
|
389
|
+
response = await self.client.apost(
|
|
390
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/prepare-upgrade",
|
|
391
|
+
bearer_token=bearer_token,
|
|
392
|
+
body=body,
|
|
393
|
+
)
|
|
394
|
+
return PrepareWalletUpgradeResponse(**response)
|
|
395
|
+
|
|
396
|
+
def prepare_wallet_upgrade(
|
|
397
|
+
self, params: PrepareWalletUpgradeParams, bearer_token: str
|
|
398
|
+
) -> PrepareWalletUpgradeResponse:
|
|
399
|
+
"""
|
|
400
|
+
Prepare a wallet upgrade (sync).
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
params: Upgrade preparation parameters
|
|
404
|
+
bearer_token: Authentication token
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
Typed data to sign for the upgrade
|
|
408
|
+
"""
|
|
409
|
+
body = {"walletAddress": params.wallet_address}
|
|
410
|
+
if params.target_class_hash:
|
|
411
|
+
body["targetClassHash"] = params.target_class_hash
|
|
412
|
+
response = self.client.post(
|
|
413
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/prepare-upgrade",
|
|
414
|
+
bearer_token=bearer_token,
|
|
415
|
+
body=body,
|
|
416
|
+
)
|
|
417
|
+
return PrepareWalletUpgradeResponse(**response)
|
|
418
|
+
|
|
419
|
+
async def aexecute_wallet_upgrade(
|
|
420
|
+
self, params: ExecuteWalletUpgradeParams, bearer_token: str
|
|
421
|
+
) -> ExecuteWalletUpgradeResponse:
|
|
422
|
+
"""
|
|
423
|
+
Execute a wallet upgrade after signing (async).
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
params: Upgrade execution parameters
|
|
427
|
+
bearer_token: Authentication token
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
Upgrade result with transaction hash
|
|
431
|
+
"""
|
|
432
|
+
response = await self.client.apost(
|
|
433
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/upgrade",
|
|
434
|
+
bearer_token=bearer_token,
|
|
435
|
+
body={
|
|
436
|
+
"walletAddress": params.wallet_address,
|
|
437
|
+
"typedData": params.typed_data,
|
|
438
|
+
"signature": params.signature,
|
|
439
|
+
},
|
|
440
|
+
)
|
|
441
|
+
return ExecuteWalletUpgradeResponse(**response)
|
|
442
|
+
|
|
443
|
+
def execute_wallet_upgrade(
|
|
444
|
+
self, params: ExecuteWalletUpgradeParams, bearer_token: str
|
|
445
|
+
) -> ExecuteWalletUpgradeResponse:
|
|
446
|
+
"""
|
|
447
|
+
Execute a wallet upgrade after signing (sync).
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
params: Upgrade execution parameters
|
|
451
|
+
bearer_token: Authentication token
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
Upgrade result with transaction hash
|
|
455
|
+
"""
|
|
456
|
+
response = self.client.post(
|
|
457
|
+
endpoint=f"{API_ENDPOINTS['CHIPI_WALLETS']}/upgrade",
|
|
458
|
+
bearer_token=bearer_token,
|
|
459
|
+
body={
|
|
460
|
+
"walletAddress": params.wallet_address,
|
|
461
|
+
"typedData": params.typed_data,
|
|
462
|
+
"signature": params.signature,
|
|
463
|
+
},
|
|
464
|
+
)
|
|
465
|
+
return ExecuteWalletUpgradeResponse(**response)
|