chipi-stack 2.1.0__tar.gz → 2.2.0__tar.gz
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_stack-2.1.0/chipi_stack.egg-info → chipi_stack-2.2.0}/PKG-INFO +27 -1
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/README.md +22 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/__init__.py +12 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/constants.py +78 -2
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/execute_paymaster.py +128 -6
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/__init__.py +2 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/wallet.py +58 -5
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/sessions.py +57 -24
- chipi_stack-2.2.0/chipi_sdk/shhh/__init__.py +249 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/compute_wallet_address.py +97 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/execute_paymaster_raw.py +439 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/migrate.py +358 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/oe.py +189 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/recovery.py +450 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/signers/__init__.py +77 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/signers/ed25519.py +157 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/signers/eip191.py +261 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/signers/jwt_apple_sub.py +517 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/signers/stark.py +92 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/snip12_hash.py +214 -0
- chipi_stack-2.2.0/chipi_sdk/shhh/threshold.py +295 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/wallets.py +223 -49
- {chipi_stack-2.1.0 → chipi_stack-2.2.0/chipi_stack.egg-info}/PKG-INFO +27 -1
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_stack.egg-info/SOURCES.txt +13 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_stack.egg-info/requires.txt +4 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/pyproject.toml +10 -1
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/LICENSE +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/MANIFEST.in +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/client.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/encryption.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/errors.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/formatters.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/core.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/session.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/sku.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/sku_purchase.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/sku_transaction.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/transaction.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/user.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/models/x402.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/py.typed +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/sdk.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/sku_purchases.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/sku_transactions.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/skus.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/transactions.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/users.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/validators.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/x402_client.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/x402_facilitator.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_sdk/x402_middleware.py +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_stack.egg-info/dependency_links.txt +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/chipi_stack.egg-info/top_level.txt +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/setup.cfg +0 -0
- {chipi_stack-2.1.0 → chipi_stack-2.2.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chipi-stack
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python SDK for Starknet Gasless Transactions via Chipi
|
|
5
5
|
Author-email: Carlos Castillo <carlos@chipipay.com>, Roberto Yamanaka <roberto@chipipay.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -25,6 +25,10 @@ Requires-Dist: pydantic>=2.0.0
|
|
|
25
25
|
Requires-Dist: httpx>=0.27.0
|
|
26
26
|
Requires-Dist: cryptography>=42.0.0
|
|
27
27
|
Requires-Dist: typing-extensions>=4.9.0
|
|
28
|
+
Requires-Dist: poseidon-py>=0.1.5
|
|
29
|
+
Requires-Dist: pycryptodome>=3.20.0
|
|
30
|
+
Requires-Dist: garaga==1.1.0
|
|
31
|
+
Requires-Dist: eth-keys>=0.5.0
|
|
28
32
|
Provides-Extra: dev
|
|
29
33
|
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
30
34
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
@@ -75,6 +79,28 @@ uv add chipi-stack
|
|
|
75
79
|
- `pydantic>=2.0.0` - Data validation
|
|
76
80
|
- `httpx>=0.27.0` - HTTP client
|
|
77
81
|
- `cryptography>=42.0.0` - AES encryption
|
|
82
|
+
- `garaga==1.1.0` - Cairo-compatible BN-curve math for SHHH Ed25519 signing
|
|
83
|
+
- `eth-keys>=0.5.0` - secp256k1 ECDSA for SHHH EIP-191 signing
|
|
84
|
+
- `poseidon-py>=0.1.5` - Poseidon hash (used by SHHH SNIP-12 envelopes)
|
|
85
|
+
- `pycryptodome>=3.20.0` - keccak256 (used by SHHH EIP-191)
|
|
86
|
+
|
|
87
|
+
### macOS Apple Silicon installation note
|
|
88
|
+
|
|
89
|
+
Garaga's BN-curve math links against libssl. On macOS 14 Sonoma+ on
|
|
90
|
+
Apple Silicon, the system libssl can mis-link during the garaga build.
|
|
91
|
+
If `pip install chipi-stack` fails with "library not loaded" or
|
|
92
|
+
"Symbol not found" mentioning `libssl` / `libcrypto`, install OpenSSL 3
|
|
93
|
+
via Homebrew and re-install:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
brew install openssl@3
|
|
97
|
+
export LDFLAGS="-L$(brew --prefix openssl@3)/lib"
|
|
98
|
+
export CPPFLAGS="-I$(brew --prefix openssl@3)/include"
|
|
99
|
+
pip install --force-reinstall chipi-stack
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Linux and Intel Macs are unaffected. Windows is untested for the SHHH
|
|
103
|
+
Ed25519 signer specifically; the rest of the SDK works on Windows.
|
|
78
104
|
|
|
79
105
|
## Quick Start
|
|
80
106
|
|
|
@@ -37,6 +37,28 @@ uv add chipi-stack
|
|
|
37
37
|
- `pydantic>=2.0.0` - Data validation
|
|
38
38
|
- `httpx>=0.27.0` - HTTP client
|
|
39
39
|
- `cryptography>=42.0.0` - AES encryption
|
|
40
|
+
- `garaga==1.1.0` - Cairo-compatible BN-curve math for SHHH Ed25519 signing
|
|
41
|
+
- `eth-keys>=0.5.0` - secp256k1 ECDSA for SHHH EIP-191 signing
|
|
42
|
+
- `poseidon-py>=0.1.5` - Poseidon hash (used by SHHH SNIP-12 envelopes)
|
|
43
|
+
- `pycryptodome>=3.20.0` - keccak256 (used by SHHH EIP-191)
|
|
44
|
+
|
|
45
|
+
### macOS Apple Silicon installation note
|
|
46
|
+
|
|
47
|
+
Garaga's BN-curve math links against libssl. On macOS 14 Sonoma+ on
|
|
48
|
+
Apple Silicon, the system libssl can mis-link during the garaga build.
|
|
49
|
+
If `pip install chipi-stack` fails with "library not loaded" or
|
|
50
|
+
"Symbol not found" mentioning `libssl` / `libcrypto`, install OpenSSL 3
|
|
51
|
+
via Homebrew and re-install:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
brew install openssl@3
|
|
55
|
+
export LDFLAGS="-L$(brew --prefix openssl@3)/lib"
|
|
56
|
+
export CPPFLAGS="-I$(brew --prefix openssl@3)/include"
|
|
57
|
+
pip install --force-reinstall chipi-stack
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Linux and Intel Macs are unaffected. Windows is untested for the SHHH
|
|
61
|
+
Ed25519 signer specifically; the rest of the SDK works on Windows.
|
|
40
62
|
|
|
41
63
|
## Quick Start
|
|
42
64
|
|
|
@@ -46,6 +46,7 @@ from .models.wallet import (
|
|
|
46
46
|
GetWalletResponse,
|
|
47
47
|
PasskeyMetadata,
|
|
48
48
|
PrepareWalletCreationResponse,
|
|
49
|
+
ShhhSignerKind,
|
|
49
50
|
WalletData,
|
|
50
51
|
WalletType,
|
|
51
52
|
PrepareWalletUpgradeParams,
|
|
@@ -163,17 +164,22 @@ from .constants import (
|
|
|
163
164
|
DEFAULT_PAGINATION,
|
|
164
165
|
ERRORS,
|
|
165
166
|
LEGACY_CHIPI_CLASS_HASHES,
|
|
167
|
+
LEGACY_SHHH_CLASS_HASHES,
|
|
166
168
|
PAYMASTER_CONFIG,
|
|
167
169
|
SERVICE_TYPES,
|
|
168
170
|
SESSION_DEFAULTS,
|
|
169
171
|
SESSION_ENTRYPOINTS,
|
|
170
172
|
SESSION_ERRORS,
|
|
173
|
+
SHHH_ENVELOPE_TAGS,
|
|
174
|
+
SHHH_KIND_GAS_OVERHEAD,
|
|
175
|
+
SHHH_VERIFIER_CLASS_HASHES,
|
|
171
176
|
SKU_CONTRACTS,
|
|
172
177
|
STARKNET_NETWORKS,
|
|
173
178
|
TOKEN_DECIMALS,
|
|
174
179
|
WALLET_CLASS_HASHES,
|
|
175
180
|
WALLET_RPC_ENDPOINTS,
|
|
176
181
|
get_wallet_type_from_class_hash,
|
|
182
|
+
is_known_shhh_class_hash,
|
|
177
183
|
)
|
|
178
184
|
|
|
179
185
|
# Utilities
|
|
@@ -236,6 +242,7 @@ __all__ = [
|
|
|
236
242
|
"PrepareWalletCreationResponse",
|
|
237
243
|
"WalletData",
|
|
238
244
|
"WalletType",
|
|
245
|
+
"ShhhSignerKind",
|
|
239
246
|
"PrepareWalletUpgradeParams",
|
|
240
247
|
"PrepareWalletUpgradeResponse",
|
|
241
248
|
"ExecuteWalletUpgradeParams",
|
|
@@ -319,7 +326,12 @@ __all__ = [
|
|
|
319
326
|
"TOKEN_DECIMALS",
|
|
320
327
|
"WALLET_CLASS_HASHES",
|
|
321
328
|
"LEGACY_CHIPI_CLASS_HASHES",
|
|
329
|
+
"LEGACY_SHHH_CLASS_HASHES",
|
|
330
|
+
"SHHH_ENVELOPE_TAGS",
|
|
331
|
+
"SHHH_KIND_GAS_OVERHEAD",
|
|
332
|
+
"SHHH_VERIFIER_CLASS_HASHES",
|
|
322
333
|
"get_wallet_type_from_class_hash",
|
|
334
|
+
"is_known_shhh_class_hash",
|
|
323
335
|
"WALLET_RPC_ENDPOINTS",
|
|
324
336
|
# Utilities
|
|
325
337
|
"camel_to_snake",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Constants used across Chipi SDK."""
|
|
2
2
|
|
|
3
3
|
from typing import Optional
|
|
4
|
-
from .models.wallet import WalletType
|
|
4
|
+
from .models.wallet import ShhhSignerKind, WalletType
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
# API Versioning
|
|
@@ -95,6 +95,7 @@ CHAIN_TOKEN_TYPES = {
|
|
|
95
95
|
WALLET_CLASS_HASHES: dict[WalletType, str] = {
|
|
96
96
|
WalletType.CHIPI: "0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1", # v33 — latest, spending policy + audit fixes
|
|
97
97
|
WalletType.READY: "0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f",
|
|
98
|
+
WalletType.SHHH: "0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a", # V8.4 ShhhAccount — declared 2026-05-15, audit-closed
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
# Previous CHIPI wallet class hashes still deployed on-chain (newest → oldest)
|
|
@@ -106,6 +107,54 @@ LEGACY_CHIPI_CLASS_HASHES: list[str] = [
|
|
|
106
107
|
"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83", # v28
|
|
107
108
|
]
|
|
108
109
|
|
|
110
|
+
# Deprecated SHHH class hashes still deployed on-chain. V8 series ships
|
|
111
|
+
# without an `upgrade` selector, so existing instances at deprecated classes
|
|
112
|
+
# cannot self-upgrade — they redeploy at the current SHHH class hash.
|
|
113
|
+
LEGACY_SHHH_CLASS_HASHES: list[str] = [
|
|
114
|
+
"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9", # V8.3 — deprecated 2026-05-15
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
# SHHH ShhhAccount verifier class hashes (V8.4, mainnet).
|
|
118
|
+
# Account dispatches `verify` to one of these via library_call_syscall based
|
|
119
|
+
# on the owner's `kind_tag`. Chipi routes as consumer; we do not redeclare.
|
|
120
|
+
SHHH_VERIFIER_CLASS_HASHES: dict[ShhhSignerKind, str] = {
|
|
121
|
+
ShhhSignerKind.STARK: "0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68",
|
|
122
|
+
ShhhSignerKind.ED25519: "0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74",
|
|
123
|
+
ShhhSignerKind.SECP256K1: "0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74",
|
|
124
|
+
ShhhSignerKind.EIP191_SECP256K1: "0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6",
|
|
125
|
+
ShhhSignerKind.EIP712_SECP256K1: "0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474",
|
|
126
|
+
ShhhSignerKind.P256: "0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a",
|
|
127
|
+
ShhhSignerKind.WEBAUTHN_P256: "0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657",
|
|
128
|
+
ShhhSignerKind.JWT_ES256: "0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497",
|
|
129
|
+
ShhhSignerKind.JWT_ES256_APPLE_SUB: "0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471",
|
|
130
|
+
ShhhSignerKind.BLS12_381: "0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1",
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
# Upper-bound l2_gas overhead per SHHH signer kind, in addition to base
|
|
134
|
+
# paymaster execution cost. Numbers from snforge runs at tag v8.4
|
|
135
|
+
# (252-byte calls, single owner, no session key). Paymaster adds ~5M margin.
|
|
136
|
+
# Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.
|
|
137
|
+
# Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.
|
|
138
|
+
SHHH_KIND_GAS_OVERHEAD: dict[ShhhSignerKind, int] = {
|
|
139
|
+
ShhhSignerKind.STARK: 2_000_000,
|
|
140
|
+
ShhhSignerKind.SECP256K1: 5_000_000,
|
|
141
|
+
ShhhSignerKind.EIP191_SECP256K1: 10_000_000,
|
|
142
|
+
ShhhSignerKind.EIP712_SECP256K1: 12_000_000,
|
|
143
|
+
ShhhSignerKind.P256: 30_000_000,
|
|
144
|
+
ShhhSignerKind.ED25519: 33_000_000,
|
|
145
|
+
ShhhSignerKind.WEBAUTHN_P256: 35_000_000,
|
|
146
|
+
ShhhSignerKind.JWT_ES256: 60_000_000,
|
|
147
|
+
ShhhSignerKind.JWT_ES256_APPLE_SUB: 62_000_000,
|
|
148
|
+
ShhhSignerKind.BLS12_381: 80_000_000,
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
# Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.
|
|
152
|
+
SHHH_ENVELOPE_TAGS = {
|
|
153
|
+
"V2_SNIP12": "V2_SNIP12",
|
|
154
|
+
"V2_THRESHOLD": "V2_THRESHOLD",
|
|
155
|
+
# Session-key envelopes are the SNIP-163 4-felt format (no version tag).
|
|
156
|
+
}
|
|
157
|
+
|
|
109
158
|
|
|
110
159
|
def get_wallet_type_from_class_hash(class_hash: str) -> Optional[str]:
|
|
111
160
|
"""
|
|
@@ -115,7 +164,7 @@ def get_wallet_type_from_class_hash(class_hash: str) -> Optional[str]:
|
|
|
115
164
|
class_hash: Class hash to look up
|
|
116
165
|
|
|
117
166
|
Returns:
|
|
118
|
-
Wallet type string ("CHIPI" or "
|
|
167
|
+
Wallet type string ("CHIPI", "READY", or "SHHH"), or None if unknown
|
|
119
168
|
"""
|
|
120
169
|
def normalize(h: str) -> str:
|
|
121
170
|
import re
|
|
@@ -129,12 +178,39 @@ def get_wallet_type_from_class_hash(class_hash: str) -> Optional[str]:
|
|
|
129
178
|
return "CHIPI"
|
|
130
179
|
if any(normalize(h) == normalized for h in LEGACY_CHIPI_CLASS_HASHES):
|
|
131
180
|
return "CHIPI"
|
|
181
|
+
if normalize(WALLET_CLASS_HASHES[WalletType.SHHH]) == normalized:
|
|
182
|
+
return "SHHH"
|
|
183
|
+
if any(normalize(h) == normalized for h in LEGACY_SHHH_CLASS_HASHES):
|
|
184
|
+
return "SHHH"
|
|
132
185
|
return None
|
|
133
186
|
|
|
187
|
+
|
|
188
|
+
def is_known_shhh_class_hash(class_hash: str) -> bool:
|
|
189
|
+
"""
|
|
190
|
+
True if a class hash is a registered SHHH ShhhAccount class (current or
|
|
191
|
+
legacy) OR one of the 10 V8.4 verifier classes. Used by the backend to
|
|
192
|
+
reject unknown class hashes when an integrator opts into SHHH via
|
|
193
|
+
wallet_type="SHHH" (plan D4 safety net — open SDK option, no per-org gate).
|
|
194
|
+
"""
|
|
195
|
+
import re
|
|
196
|
+
|
|
197
|
+
def normalize(h: str) -> str:
|
|
198
|
+
return re.sub(r"^0x0+", "0x", h.lower())
|
|
199
|
+
|
|
200
|
+
normalized = normalize(class_hash)
|
|
201
|
+
|
|
202
|
+
if normalize(WALLET_CLASS_HASHES[WalletType.SHHH]) == normalized:
|
|
203
|
+
return True
|
|
204
|
+
if any(normalize(h) == normalized for h in LEGACY_SHHH_CLASS_HASHES):
|
|
205
|
+
return True
|
|
206
|
+
return any(normalize(h) == normalized for h in SHHH_VERIFIER_CLASS_HASHES.values())
|
|
207
|
+
|
|
208
|
+
|
|
134
209
|
# RPC Endpoints per Wallet Type
|
|
135
210
|
WALLET_RPC_ENDPOINTS: dict[WalletType, str] = {
|
|
136
211
|
WalletType.CHIPI: "https://starknet-mainnet.public.blastapi.io/rpc/v0_7",
|
|
137
212
|
WalletType.READY: "https://cloud.argent-api.com/v1/starknet/mainnet/rpc/v0.7",
|
|
213
|
+
WalletType.SHHH: "https://starknet-mainnet.public.blastapi.io/rpc/v0_7",
|
|
138
214
|
}
|
|
139
215
|
|
|
140
216
|
# Paymaster Configuration
|
|
@@ -58,6 +58,34 @@ async def execute_paymaster_transaction(
|
|
|
58
58
|
)
|
|
59
59
|
raise ValueError(error_msg)
|
|
60
60
|
|
|
61
|
+
# SHHH V8.4 ShhhAccount wallets cannot use the legacy
|
|
62
|
+
# prepare-typed-data → sign → execute-sponsored-transaction
|
|
63
|
+
# flow because the Chipi paymaster cannot synthesize SHHH
|
|
64
|
+
# envelopes server-side. Route SHHH OEs through the
|
|
65
|
+
# execute-sponsored-raw forwarder which expects pre-signed
|
|
66
|
+
# calldata. The legacy flow below is unchanged for
|
|
67
|
+
# CHIPI / READY.
|
|
68
|
+
if wallet.wallet_type == WalletType.SHHH:
|
|
69
|
+
from .shhh.execute_paymaster_raw import execute_shhh_sponsored_raw
|
|
70
|
+
from .shhh.snip12_hash import Call as ShhhCall
|
|
71
|
+
|
|
72
|
+
shhh_calls = [
|
|
73
|
+
ShhhCall(
|
|
74
|
+
contract_address=c.get("contractAddress") or c.get("to"),
|
|
75
|
+
entrypoint=c["entrypoint"],
|
|
76
|
+
calldata=list(c.get("calldata") or []),
|
|
77
|
+
)
|
|
78
|
+
for c in calls
|
|
79
|
+
]
|
|
80
|
+
return await execute_shhh_sponsored_raw(
|
|
81
|
+
client=client,
|
|
82
|
+
bearer_token=bearer_token,
|
|
83
|
+
wallet_public_key=wallet.public_key,
|
|
84
|
+
wallet_encrypted_private_key=wallet.encrypted_private_key,
|
|
85
|
+
encrypt_key=encrypt_key,
|
|
86
|
+
calls=shhh_calls,
|
|
87
|
+
)
|
|
88
|
+
|
|
61
89
|
# Use READY RPC endpoint for now (matches TypeScript implementation)
|
|
62
90
|
rpc_url = WALLET_RPC_ENDPOINTS[WalletType.READY]
|
|
63
91
|
account_class_hash = WALLET_CLASS_HASHES[WalletType.READY]
|
|
@@ -168,6 +196,33 @@ def execute_paymaster_transaction_sync(
|
|
|
168
196
|
)
|
|
169
197
|
raise ValueError(error_msg)
|
|
170
198
|
|
|
199
|
+
# SHHH parity for the sync API. Sync callers with WalletType.SHHH
|
|
200
|
+
# would otherwise fall into the legacy prepare-typed-data flow,
|
|
201
|
+
# which the paymaster cannot synthesize an envelope for and
|
|
202
|
+
# returns TRANSACTION_EXECUTION_ERROR. Mirror the async branch
|
|
203
|
+
# above via execute_shhh_sponsored_raw_sync (shared payload
|
|
204
|
+
# construction, sync HTTP).
|
|
205
|
+
if wallet.wallet_type == WalletType.SHHH:
|
|
206
|
+
from .shhh.execute_paymaster_raw import execute_shhh_sponsored_raw_sync
|
|
207
|
+
from .shhh.snip12_hash import Call as ShhhCall
|
|
208
|
+
|
|
209
|
+
shhh_calls = [
|
|
210
|
+
ShhhCall(
|
|
211
|
+
contract_address=c.get("contractAddress") or c.get("to"),
|
|
212
|
+
entrypoint=c["entrypoint"],
|
|
213
|
+
calldata=list(c.get("calldata") or []),
|
|
214
|
+
)
|
|
215
|
+
for c in calls
|
|
216
|
+
]
|
|
217
|
+
return execute_shhh_sponsored_raw_sync(
|
|
218
|
+
client=client,
|
|
219
|
+
bearer_token=bearer_token,
|
|
220
|
+
wallet_public_key=wallet.public_key,
|
|
221
|
+
wallet_encrypted_private_key=wallet.encrypted_private_key,
|
|
222
|
+
encrypt_key=encrypt_key,
|
|
223
|
+
calls=shhh_calls,
|
|
224
|
+
)
|
|
225
|
+
|
|
171
226
|
# Use READY account class hash (matches TypeScript implementation)
|
|
172
227
|
account_class_hash = WALLET_CLASS_HASHES[WalletType.READY]
|
|
173
228
|
|
|
@@ -260,10 +315,15 @@ async def execute_paymaster_transaction_with_session(
|
|
|
260
315
|
else:
|
|
261
316
|
session = session_dict
|
|
262
317
|
|
|
263
|
-
#
|
|
264
|
-
|
|
318
|
+
# Accept CHIPI v29 + SHHH V8.4 (both embed SNIP-163 sessions;
|
|
319
|
+
# the 4-felt session sig fast path at account.cairo:389 runs
|
|
320
|
+
# the same on either class).
|
|
321
|
+
if wallet.wallet_type and wallet.wallet_type not in (
|
|
322
|
+
WalletType.CHIPI,
|
|
323
|
+
WalletType.SHHH,
|
|
324
|
+
):
|
|
265
325
|
raise ChipiSessionError(
|
|
266
|
-
f"Session
|
|
326
|
+
f"Session execution requires CHIPI or SHHH wallet type. Got: {wallet.wallet_type}",
|
|
267
327
|
SESSION_ERRORS["INVALID_WALLET_TYPE_FOR_SESSION"],
|
|
268
328
|
)
|
|
269
329
|
|
|
@@ -275,6 +335,34 @@ async def execute_paymaster_transaction_with_session(
|
|
|
275
335
|
if not session_private_key:
|
|
276
336
|
raise ValueError("Failed to decrypt session private key")
|
|
277
337
|
|
|
338
|
+
# SHHH branch — route through V8.4 OE path with the 4-felt
|
|
339
|
+
# session sig (bypasses chipi-back's CHIPI-shaped
|
|
340
|
+
# prepare-typed-data + execute-sponsored-transaction). Mirrors
|
|
341
|
+
# the TypeScript SHHH branch shipped in sdks#288.
|
|
342
|
+
if wallet.wallet_type == WalletType.SHHH:
|
|
343
|
+
from .shhh.execute_paymaster_raw import (
|
|
344
|
+
execute_shhh_session_sponsored_raw,
|
|
345
|
+
)
|
|
346
|
+
from .shhh.snip12_hash import Call as ShhhCall
|
|
347
|
+
|
|
348
|
+
shhh_calls = [
|
|
349
|
+
ShhhCall(
|
|
350
|
+
contract_address=c.get("contractAddress") or c.get("to"),
|
|
351
|
+
entrypoint=c["entrypoint"],
|
|
352
|
+
calldata=list(c.get("calldata") or []),
|
|
353
|
+
)
|
|
354
|
+
for c in calls
|
|
355
|
+
]
|
|
356
|
+
return await execute_shhh_session_sponsored_raw(
|
|
357
|
+
client=client,
|
|
358
|
+
bearer_token=bearer_token,
|
|
359
|
+
wallet_public_key=wallet.public_key,
|
|
360
|
+
session_private_key=session_private_key,
|
|
361
|
+
session_public_key=session.public_key,
|
|
362
|
+
session_valid_until=session.valid_until,
|
|
363
|
+
calls=shhh_calls,
|
|
364
|
+
)
|
|
365
|
+
|
|
278
366
|
# Use CHIPI RPC endpoint and class hash
|
|
279
367
|
account_class_hash = WALLET_CLASS_HASHES[WalletType.CHIPI]
|
|
280
368
|
|
|
@@ -375,13 +463,47 @@ def execute_paymaster_transaction_with_session_sync(
|
|
|
375
463
|
else:
|
|
376
464
|
session = session_dict
|
|
377
465
|
|
|
378
|
-
#
|
|
379
|
-
if wallet.wallet_type and wallet.wallet_type
|
|
466
|
+
# Accept CHIPI v29 + SHHH V8.4 — see async path above for details.
|
|
467
|
+
if wallet.wallet_type and wallet.wallet_type not in (
|
|
468
|
+
WalletType.CHIPI,
|
|
469
|
+
WalletType.SHHH,
|
|
470
|
+
):
|
|
380
471
|
raise ChipiSessionError(
|
|
381
|
-
f"Session
|
|
472
|
+
f"Session execution requires CHIPI or SHHH wallet type. Got: {wallet.wallet_type}",
|
|
382
473
|
SESSION_ERRORS["INVALID_WALLET_TYPE_FOR_SESSION"],
|
|
383
474
|
)
|
|
384
475
|
|
|
476
|
+
# SHHH branch (sync) — same shape as the async path.
|
|
477
|
+
if wallet.wallet_type == WalletType.SHHH:
|
|
478
|
+
session_private_key_sync = decrypt_private_key(
|
|
479
|
+
session.encrypted_private_key, params["encryptKey"]
|
|
480
|
+
)
|
|
481
|
+
if not session_private_key_sync:
|
|
482
|
+
raise ValueError("Failed to decrypt session private key")
|
|
483
|
+
|
|
484
|
+
from .shhh.execute_paymaster_raw import (
|
|
485
|
+
execute_shhh_session_sponsored_raw_sync,
|
|
486
|
+
)
|
|
487
|
+
from .shhh.snip12_hash import Call as ShhhCall
|
|
488
|
+
|
|
489
|
+
shhh_calls = [
|
|
490
|
+
ShhhCall(
|
|
491
|
+
contract_address=c.get("contractAddress") or c.get("to"),
|
|
492
|
+
entrypoint=c["entrypoint"],
|
|
493
|
+
calldata=list(c.get("calldata") or []),
|
|
494
|
+
)
|
|
495
|
+
for c in calls
|
|
496
|
+
]
|
|
497
|
+
return execute_shhh_session_sponsored_raw_sync(
|
|
498
|
+
client=client,
|
|
499
|
+
bearer_token=bearer_token,
|
|
500
|
+
wallet_public_key=wallet.public_key,
|
|
501
|
+
session_private_key=session_private_key_sync,
|
|
502
|
+
session_public_key=session.public_key,
|
|
503
|
+
session_valid_until=session.valid_until,
|
|
504
|
+
calls=shhh_calls,
|
|
505
|
+
)
|
|
506
|
+
|
|
385
507
|
# Use CHIPI account class hash
|
|
386
508
|
account_class_hash = WALLET_CLASS_HASHES[WalletType.CHIPI]
|
|
387
509
|
|
|
@@ -23,6 +23,7 @@ from .wallet import (
|
|
|
23
23
|
GetWalletResponse,
|
|
24
24
|
PasskeyMetadata,
|
|
25
25
|
PrepareWalletCreationResponse,
|
|
26
|
+
ShhhSignerKind,
|
|
26
27
|
WalletData,
|
|
27
28
|
WalletType,
|
|
28
29
|
)
|
|
@@ -101,6 +102,7 @@ __all__ = [
|
|
|
101
102
|
"GetWalletResponse",
|
|
102
103
|
"PasskeyMetadata",
|
|
103
104
|
"PrepareWalletCreationResponse",
|
|
105
|
+
"ShhhSignerKind",
|
|
104
106
|
"WalletData",
|
|
105
107
|
"WalletType",
|
|
106
108
|
# Transaction
|
|
@@ -17,12 +17,41 @@ def to_camel(string: str) -> str:
|
|
|
17
17
|
class WalletType(str, Enum):
|
|
18
18
|
"""
|
|
19
19
|
Supported wallet types.
|
|
20
|
-
|
|
21
|
-
- CHIPI: OpenZeppelin account with SNIP-9 session keys support (
|
|
22
|
-
- READY: Argent X Account v0.4.0
|
|
20
|
+
|
|
21
|
+
- CHIPI: OpenZeppelin account with SNIP-9 session keys support (legacy v29).
|
|
22
|
+
- READY: Argent X Account v0.4.0.
|
|
23
|
+
- SHHH (default post-P2.2): V8.4 ShhhAccount — pluggable-signer
|
|
24
|
+
Starknet account dispatching to one of 10 verifier classes (STARK,
|
|
25
|
+
ED25519, SECP256K1, EIP191/EIP712, P256, WEBAUTHN_P256, JWT_ES256,
|
|
26
|
+
JWT_ES256_APPLE_SUB, BLS12_381). Requires CHIPI_SHHH_ENABLED on
|
|
27
|
+
the backend.
|
|
23
28
|
"""
|
|
24
29
|
CHIPI = "CHIPI"
|
|
25
30
|
READY = "READY"
|
|
31
|
+
SHHH = "SHHH"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ShhhSignerKind(str, Enum):
|
|
35
|
+
"""
|
|
36
|
+
SHHH signer kinds (V8.4 ShhhAccount). The `kind_tag` value the account
|
|
37
|
+
uses to dispatch `verify` to the matching verifier class via
|
|
38
|
+
library_call_syscall. See SHHH_VERIFIER_CLASS_HASHES and
|
|
39
|
+
SHHH_KIND_GAS_OVERHEAD in chipi_sdk.constants.
|
|
40
|
+
|
|
41
|
+
No WebAuthn signer in Python — server-side only; WebAuthn requires a
|
|
42
|
+
browser/RN context. Wallet creation with wallet_type=SHHH and no
|
|
43
|
+
signer_kind raises in Python (per plan D10).
|
|
44
|
+
"""
|
|
45
|
+
STARK = "STARK"
|
|
46
|
+
ED25519 = "ED25519"
|
|
47
|
+
SECP256K1 = "SECP256K1"
|
|
48
|
+
EIP191_SECP256K1 = "EIP191_SECP256K1"
|
|
49
|
+
EIP712_SECP256K1 = "EIP712_SECP256K1"
|
|
50
|
+
P256 = "P256"
|
|
51
|
+
WEBAUTHN_P256 = "WEBAUTHN_P256"
|
|
52
|
+
JWT_ES256 = "JWT_ES256"
|
|
53
|
+
JWT_ES256_APPLE_SUB = "JWT_ES256_APPLE_SUB"
|
|
54
|
+
BLS12_381 = "BLS12_381"
|
|
26
55
|
|
|
27
56
|
|
|
28
57
|
class WalletData(BaseModel):
|
|
@@ -47,12 +76,36 @@ class DeploymentData(BaseModel):
|
|
|
47
76
|
|
|
48
77
|
class CreateWalletParams(BaseModel):
|
|
49
78
|
"""Parameters for creating a new wallet."""
|
|
50
|
-
|
|
79
|
+
|
|
51
80
|
encrypt_key: Optional[str] = Field(None, description="Encryption key for private key")
|
|
52
81
|
external_user_id: str = Field(..., description="External user identifier")
|
|
53
82
|
user_id: Optional[str] = Field(None, description="Internal user ID")
|
|
54
|
-
|
|
83
|
+
# P2.2 default flip (re-applied 2026-05-29 after #270 revert and the
|
|
84
|
+
# post-revert SHHH bug-fix run). Mirrors the TS SDK default and
|
|
85
|
+
# matches every production mainnet smoke from 2026-05-26 onward.
|
|
86
|
+
# Callers who explicitly pass wallet_type=CHIPI / READY are
|
|
87
|
+
# unaffected.
|
|
88
|
+
wallet_type: Optional[WalletType] = Field(
|
|
89
|
+
WalletType.SHHH,
|
|
90
|
+
description="Type of wallet to create (defaults to SHHH V8.4 post-P2.2)",
|
|
91
|
+
)
|
|
55
92
|
use_passkey: Optional[bool] = Field(False, description="Whether to use passkey authentication")
|
|
93
|
+
signer_kind: Optional[ShhhSignerKind] = Field(
|
|
94
|
+
None,
|
|
95
|
+
description=(
|
|
96
|
+
"Required when wallet_type=SHHH is set EXPLICITLY. When SHHH "
|
|
97
|
+
"is reached via the default-flip (caller omitted wallet_type), "
|
|
98
|
+
"the SDK falls back to STARK to match the TS SDK and the live "
|
|
99
|
+
"on-chain smokes. Wallet CREATION from Python currently "
|
|
100
|
+
"supports STARK only — non-STARK kinds (ED25519, "
|
|
101
|
+
"EIP191_SECP256K1, etc.) raise NotImplementedError at create "
|
|
102
|
+
"time and will be enabled by a follow-up PR that adds the "
|
|
103
|
+
"external-rooted (MetaMask, Phantom, Apple) wallet-adapter "
|
|
104
|
+
"deploy paths. The chipi_sdk.shhh envelope BUILDERS for those "
|
|
105
|
+
"kinds remain usable today for signing OEs on existing SHHH "
|
|
106
|
+
"wallets (see chipi_sdk.shhh.signers)."
|
|
107
|
+
),
|
|
108
|
+
)
|
|
56
109
|
|
|
57
110
|
|
|
58
111
|
class GetWalletResponse(BaseModel):
|