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
- accepted = parse_payment_required(
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
- def parse_payment_required(header: str | None) -> PaymentRequirements:
43
- """Decode the base64 PAYMENT-REQUIRED header and return the first accepted option.
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
- return accepts[0]
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 PaymentRequirements(
60
- scheme="exact",
61
- network="eip155:8453",
62
- amount="0",
63
- asset="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
64
- payTo="",
65
- maxTimeoutSeconds=300,
66
- extra={"name": "USD Coin", "version": "2"},
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
- return {
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oneshot-python
3
- Version: 0.7.0
3
+ Version: 0.7.2
4
4
  Summary: Core Python SDK for the OneShot API — HTTP client with x402 payment handling
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
@@ -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,,