oneshot-python 0.7.0__py3-none-any.whl → 0.7.2__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.
oneshot/client.py
CHANGED
|
@@ -137,9 +137,10 @@ class OneShotClient:
|
|
|
137
137
|
|
|
138
138
|
# Step 2 — Parse 402 response
|
|
139
139
|
# Parse x402 v2 PaymentRequired from PAYMENT-REQUIRED header
|
|
140
|
-
|
|
140
|
+
parsed_req = parse_payment_required(
|
|
141
141
|
resp.headers.get("payment-required")
|
|
142
142
|
)
|
|
143
|
+
accepted = parsed_req["accepted"]
|
|
143
144
|
|
|
144
145
|
quote_data = resp.json()
|
|
145
146
|
payment_request = quote_data["payment_request"]
|
|
@@ -156,7 +157,7 @@ class OneShotClient:
|
|
|
156
157
|
|
|
157
158
|
self._log(f"Payment required: {payment_request['amount']} USDC")
|
|
158
159
|
|
|
159
|
-
# Step 3 — Sign x402 payment (v2 format with accepted requirements)
|
|
160
|
+
# Step 3 — Sign x402 payment (v2 format with accepted requirements + Bazaar metadata)
|
|
160
161
|
auth = sign_payment_authorization(
|
|
161
162
|
private_key=self._private_key,
|
|
162
163
|
from_address=self.address,
|
|
@@ -166,14 +167,14 @@ class OneShotClient:
|
|
|
166
167
|
chain_id=payment_request["chain_id"],
|
|
167
168
|
network=f"eip155:{payment_request['chain_id']}",
|
|
168
169
|
accepted=accepted,
|
|
170
|
+
resource=parsed_req.get("resource"),
|
|
171
|
+
extensions=parsed_req.get("extensions"),
|
|
169
172
|
)
|
|
170
173
|
|
|
171
174
|
# Step 4 — Re-POST with payment headers (x402 format)
|
|
172
|
-
auth_json = json.dumps(auth)
|
|
173
175
|
headers = {
|
|
174
176
|
**self._headers(),
|
|
175
177
|
"payment-signature": encode_payment_header(auth),
|
|
176
|
-
"x-payment": auth_json, # backwards compat for identity extraction
|
|
177
178
|
}
|
|
178
179
|
if quote_id:
|
|
179
180
|
headers["x-quote-id"] = quote_id
|
oneshot/x402.py
CHANGED
|
@@ -39,8 +39,16 @@ class PaymentAuthorization(TypedDict):
|
|
|
39
39
|
payload: dict[str, Any]
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
"""
|
|
42
|
+
class ParsedPaymentRequired(TypedDict, total=False):
|
|
43
|
+
"""Full parsed 402 response with Bazaar discovery metadata."""
|
|
44
|
+
|
|
45
|
+
accepted: PaymentRequirements
|
|
46
|
+
resource: dict[str, Any]
|
|
47
|
+
extensions: dict[str, Any]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def parse_payment_required(header: str | None) -> ParsedPaymentRequired:
|
|
51
|
+
"""Decode the base64 PAYMENT-REQUIRED header and return accepted requirements + Bazaar metadata.
|
|
44
52
|
|
|
45
53
|
Falls back to sensible defaults if the header is missing or unparseable.
|
|
46
54
|
"""
|
|
@@ -48,22 +56,29 @@ def parse_payment_required(header: str | None) -> PaymentRequirements:
|
|
|
48
56
|
try:
|
|
49
57
|
decoded = base64.b64decode(header).decode()
|
|
50
58
|
parsed = json.loads(decoded)
|
|
51
|
-
# x402 v2: { x402Version: 2, accepts: [...], resource: {...} }
|
|
59
|
+
# x402 v2: { x402Version: 2, accepts: [...], resource: {...}, extensions: {...} }
|
|
52
60
|
accepts = parsed.get("accepts", [])
|
|
53
61
|
if accepts:
|
|
54
|
-
|
|
62
|
+
result: ParsedPaymentRequired = {"accepted": accepts[0]}
|
|
63
|
+
if parsed.get("resource"):
|
|
64
|
+
result["resource"] = parsed["resource"]
|
|
65
|
+
if parsed.get("extensions"):
|
|
66
|
+
result["extensions"] = parsed["extensions"]
|
|
67
|
+
return result
|
|
55
68
|
except Exception:
|
|
56
69
|
pass
|
|
57
70
|
|
|
58
71
|
# Fallback with production defaults
|
|
59
|
-
return
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
return ParsedPaymentRequired(
|
|
73
|
+
accepted=PaymentRequirements(
|
|
74
|
+
scheme="exact",
|
|
75
|
+
network="eip155:8453",
|
|
76
|
+
amount="0",
|
|
77
|
+
asset="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
78
|
+
payTo="",
|
|
79
|
+
maxTimeoutSeconds=300,
|
|
80
|
+
extra={"name": "USD Coin", "version": "2"},
|
|
81
|
+
),
|
|
67
82
|
)
|
|
68
83
|
|
|
69
84
|
|
|
@@ -77,6 +92,8 @@ def sign_payment_authorization(
|
|
|
77
92
|
chain_id: int,
|
|
78
93
|
network: str,
|
|
79
94
|
accepted: PaymentRequirements | None = None,
|
|
95
|
+
resource: dict[str, Any] | None = None,
|
|
96
|
+
extensions: dict[str, Any] | None = None,
|
|
80
97
|
) -> dict[str, Any]:
|
|
81
98
|
"""Create an EIP-712 TransferWithAuthorization signature for USDC.
|
|
82
99
|
|
|
@@ -89,6 +106,8 @@ def sign_payment_authorization(
|
|
|
89
106
|
chain_id: EVM chain ID (8453 for Base Mainnet).
|
|
90
107
|
network: CAIP-2 network string (e.g. "eip155:8453").
|
|
91
108
|
accepted: Parsed PaymentRequirements from server's PAYMENT-REQUIRED header.
|
|
109
|
+
resource: Resource metadata from 402 response (for Bazaar discovery).
|
|
110
|
+
extensions: Extensions from 402 response (for Bazaar discovery).
|
|
92
111
|
|
|
93
112
|
Returns:
|
|
94
113
|
x402 PaymentPayload v2 dict.
|
|
@@ -150,8 +169,8 @@ def sign_payment_authorization(
|
|
|
150
169
|
extra={"name": domain_name, "version": domain_version},
|
|
151
170
|
)
|
|
152
171
|
|
|
153
|
-
# x402 PaymentPayload v2 format
|
|
154
|
-
|
|
172
|
+
# x402 PaymentPayload v2 format (including resource + extensions for Bazaar discovery)
|
|
173
|
+
result: dict[str, Any] = {
|
|
155
174
|
"x402Version": 2,
|
|
156
175
|
"accepted": dict(accepted_req),
|
|
157
176
|
"payload": {
|
|
@@ -166,6 +185,11 @@ def sign_payment_authorization(
|
|
|
166
185
|
},
|
|
167
186
|
},
|
|
168
187
|
}
|
|
188
|
+
if resource:
|
|
189
|
+
result["resource"] = resource
|
|
190
|
+
if extensions:
|
|
191
|
+
result["extensions"] = extensions
|
|
192
|
+
return result
|
|
169
193
|
|
|
170
194
|
|
|
171
195
|
def encode_payment_header(auth: dict[str, Any]) -> str:
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
oneshot/__init__.py,sha256=yDrp5FGVWFLuMZUBzS2exrdizzBAWXZXS1VVoesmUuM,498
|
|
2
|
+
oneshot/_errors.py,sha256=hbDMBck3JU3pFlNvSKMWZ4j1uFsyTQNciFVjAatE5rc,1432
|
|
3
|
+
oneshot/client.py,sha256=oV26cggfU_VAKCE_DjBgwmWr3GN-wdhUI-tKtMmgkWM,12174
|
|
4
|
+
oneshot/x402.py,sha256=4tf6E9WqGOEKLud-YMtIRlcSkA0UaRrPomRA3exPKsE,6872
|
|
5
|
+
oneshot_python-0.7.2.dist-info/METADATA,sha256=WEHYwAxxL789mqTR7WPAc5N-nFWwx55auaphG0xXD18,446
|
|
6
|
+
oneshot_python-0.7.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
+
oneshot_python-0.7.2.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
oneshot/__init__.py,sha256=yDrp5FGVWFLuMZUBzS2exrdizzBAWXZXS1VVoesmUuM,498
|
|
2
|
-
oneshot/_errors.py,sha256=hbDMBck3JU3pFlNvSKMWZ4j1uFsyTQNciFVjAatE5rc,1432
|
|
3
|
-
oneshot/client.py,sha256=CIy1RekFe-UHnRIdc9Pkntln6s-frl8HjcqUOE9AsWs,12123
|
|
4
|
-
oneshot/x402.py,sha256=yDp0R9X3NZFpM4gRK9J6YxCB6kPfQC2R1DXGXPzAbAE,5812
|
|
5
|
-
oneshot_python-0.7.0.dist-info/METADATA,sha256=aQisHnhe39kNaRG8O0dUZcj92PQ1JCJUrnl9m0Fo8J4,446
|
|
6
|
-
oneshot_python-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
-
oneshot_python-0.7.0.dist-info/RECORD,,
|
|
File without changes
|