patchr 0.1.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.
Files changed (116) hide show
  1. apps/__init__.py +2 -0
  2. apps/api/__init__.py +2 -0
  3. apps/api/main.py +652 -0
  4. apps/benchmarks/__init__.py +1 -0
  5. apps/benchmarks/main.py +20 -0
  6. apps/sandbox/__init__.py +1 -0
  7. apps/sandbox/main.py +20 -0
  8. apps/worker/__init__.py +2 -0
  9. apps/worker/main.py +15 -0
  10. apps/worker/verify.py +14 -0
  11. patchr/__init__.py +12 -0
  12. patchr/sdk/__init__.py +20 -0
  13. patchr/sdk/client.py +12 -0
  14. patchr-0.1.0.dist-info/METADATA +137 -0
  15. patchr-0.1.0.dist-info/RECORD +116 -0
  16. patchr-0.1.0.dist-info/WHEEL +5 -0
  17. patchr-0.1.0.dist-info/entry_points.txt +5 -0
  18. patchr-0.1.0.dist-info/licenses/LICENSE +17 -0
  19. patchr-0.1.0.dist-info/top_level.txt +3 -0
  20. picux/__init__.py +6 -0
  21. picux/agents/__init__.py +5 -0
  22. picux/agents/registry.py +204 -0
  23. picux/api/__init__.py +5 -0
  24. picux/api/service.py +5075 -0
  25. picux/audit/__init__.py +31 -0
  26. picux/audit/activity.py +97 -0
  27. picux/audit/observability.py +55 -0
  28. picux/audit/verification/__init__.py +21 -0
  29. picux/audit/verification/ledger.py +633 -0
  30. picux/benchmarks/__init__.py +5 -0
  31. picux/benchmarks/local.py +286 -0
  32. picux/config.py +140 -0
  33. picux/contracts/__init__.py +22 -0
  34. picux/contracts/handshake.py +122 -0
  35. picux/contracts/integration.py +385 -0
  36. picux/contracts/openapi.py +187 -0
  37. picux/contracts/protocol_map.py +152 -0
  38. picux/contracts/routes.py +980 -0
  39. picux/contracts/schema_catalog.py +125 -0
  40. picux/core/__init__.py +17 -0
  41. picux/core/models.py +148 -0
  42. picux/core/router.py +131 -0
  43. picux/core/runtime.py +42 -0
  44. picux/core/state_machine.py +38 -0
  45. picux/domains/__init__.py +2 -0
  46. picux/domains/bridge/HostRun.py +1104 -0
  47. picux/domains/bridge/__init__.py +6 -0
  48. picux/domains/bridge/engine.py +345 -0
  49. picux/domains/hunt/__init__.py +6 -0
  50. picux/domains/hunt/engine.py +307 -0
  51. picux/domains/hunt/models.py +88 -0
  52. picux/domains/pay/__init__.py +16 -0
  53. picux/domains/pay/adapters.py +607 -0
  54. picux/domains/pay/engine.py +950 -0
  55. picux/domains/pay/models.py +95 -0
  56. picux/domains/proxy/__init__.py +5 -0
  57. picux/domains/proxy/engine.py +466 -0
  58. picux/domains/resolve/__init__.py +5 -0
  59. picux/domains/resolve/engine.py +546 -0
  60. picux/orchestrator/__init__.py +3 -0
  61. picux/orchestrator/engine.py +2840 -0
  62. picux/portals/__init__.py +17 -0
  63. picux/portals/templates.py +272 -0
  64. picux/protocols/__init__.py +1 -0
  65. picux/protocols/a2a/__init__.py +6 -0
  66. picux/protocols/a2a/client.py +51 -0
  67. picux/protocols/a2a/envelope.py +132 -0
  68. picux/protocols/mcp/__init__.py +7 -0
  69. picux/protocols/mcp/client.py +69 -0
  70. picux/protocols/mcp/contract.py +67 -0
  71. picux/protocols/mcp/server.py +76 -0
  72. picux/sandbox/__init__.py +6 -0
  73. picux/sandbox/midnight_arbitrage.py +215 -0
  74. picux/sandbox/models.py +90 -0
  75. picux/sdk/__init__.py +13 -0
  76. picux/sdk/client.py +768 -0
  77. picux/sdk/external.py +245 -0
  78. picux/security/__init__.py +18 -0
  79. picux/security/auth.py +86 -0
  80. picux/security/config_validator.py +58 -0
  81. picux/security/policy.py +158 -0
  82. picux/security/secrets.py +144 -0
  83. picux/signals/__init__.py +1 -0
  84. picux/signals/community/__init__.py +24 -0
  85. picux/signals/community/adapters/__init__.py +7 -0
  86. picux/signals/community/adapters/reddit.py +37 -0
  87. picux/signals/community/adapters/shopify.py +23 -0
  88. picux/signals/community/adapters/web.py +23 -0
  89. picux/signals/community/disambiguation.py +51 -0
  90. picux/signals/community/intake.py +227 -0
  91. picux/signals/community/models.py +102 -0
  92. picux/signals/community/rules.py +91 -0
  93. picux/signals/community/scoring.py +64 -0
  94. picux/storage/__init__.py +41 -0
  95. picux/storage/agents.py +50 -0
  96. picux/storage/cases.py +440 -0
  97. picux/storage/channels.py +476 -0
  98. picux/storage/connectors.py +411 -0
  99. picux/storage/envelopes.py +137 -0
  100. picux/storage/escrows.py +168 -0
  101. picux/storage/events.py +989 -0
  102. picux/storage/keyspace.py +60 -0
  103. picux/storage/mandates.py +107 -0
  104. picux/storage/portals.py +222 -0
  105. picux/storage/postgres.py +2049 -0
  106. picux/storage/providers.py +148 -0
  107. picux/storage/proxy.py +231 -0
  108. picux/storage/receipts.py +131 -0
  109. picux/storage/signals.py +147 -0
  110. picux/storage/tasks.py +179 -0
  111. picux/tools/__init__.py +11 -0
  112. picux/tools/shared.py +2048 -0
  113. picux/verification/__init__.py +5 -0
  114. picux/verification/rollout.py +183 -0
  115. picux/workflows/__init__.py +5 -0
  116. picux/workflows/templates.py +74 -0
@@ -0,0 +1,607 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ from dataclasses import dataclass
6
+ from typing import Any, Mapping
7
+ from urllib import error, request
8
+ from urllib.parse import urlparse
9
+
10
+
11
+ def stableId(prefix: str, payload: dict[str, Any]) -> str:
12
+ raw = json.dumps(payload, ensure_ascii=True, sort_keys=True, separators=(",", ":")).encode("utf-8")
13
+ return f"{prefix}_" + hashlib.sha256(raw).hexdigest()[:24]
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class PayRailAdapterContext:
18
+ env: Mapping[str, str]
19
+ createdAt: str
20
+
21
+
22
+ class PayRailAdapter:
23
+ adapterId = ""
24
+ railId = ""
25
+ status = "contract"
26
+ mode = "verify"
27
+ capabilities: tuple[str, ...] = ()
28
+ requiredEnv: tuple[str, ...] = ()
29
+ envAliases: dict[str, tuple[str, ...]] = {}
30
+ liveExecution = False
31
+
32
+ def metadata(self, env: Mapping[str, str]) -> dict[str, Any]:
33
+ readiness = self.readiness(env)
34
+ return {
35
+ "adapterId": self.adapterId,
36
+ "railId": self.railId,
37
+ "status": self.status,
38
+ "mode": self.mode,
39
+ "capabilities": list(self.capabilities),
40
+ "requiredEnv": list(self.requiredEnv),
41
+ "liveExecution": self.liveExecution,
42
+ "configured": readiness["configured"],
43
+ "missingEnv": readiness["missingEnv"],
44
+ "resolvedEnv": readiness.get("resolvedEnv", {}),
45
+ "readiness": readiness,
46
+ }
47
+
48
+ def readiness(self, env: Mapping[str, str]) -> dict[str, Any]:
49
+ resolved = {key: self.envKey(env, key) for key in self.requiredEnv}
50
+ missing = [key for key, source in resolved.items() if not source]
51
+ return {
52
+ "configured": not missing,
53
+ "missingEnv": missing,
54
+ "resolvedEnv": {key: source for key, source in resolved.items() if source},
55
+ "mode": "live" if not missing and self.liveExecution else "prepare",
56
+ }
57
+
58
+ def envKey(self, env: Mapping[str, str], key: str) -> str:
59
+ keys = (key, *self.envAliases.get(key, ()))
60
+ return next((candidate for candidate in keys if str(env.get(candidate, "") or "").strip()), "")
61
+
62
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
63
+ readiness = self.readiness(context.env)
64
+ if not readiness["configured"]:
65
+ return self.blocked(action, context, readiness)
66
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
67
+
68
+ def blocked(self, action: str, context: PayRailAdapterContext, readiness: dict[str, Any] | None = None) -> dict[str, Any]:
69
+ readiness = readiness or self.readiness(context.env)
70
+ return {
71
+ "ok": False,
72
+ "adapterId": self.adapterId,
73
+ "railId": self.railId,
74
+ "action": action,
75
+ "status": "blocked",
76
+ "error": "adapterNotConfigured",
77
+ "missingEnv": readiness.get("missingEnv", []),
78
+ "readiness": readiness,
79
+ "liveExecution": self.liveExecution,
80
+ "createdAt": context.createdAt,
81
+ }
82
+
83
+ def unsupported(self, action: str, context: PayRailAdapterContext, error: str) -> dict[str, Any]:
84
+ return {
85
+ "ok": False,
86
+ "adapterId": self.adapterId,
87
+ "railId": self.railId,
88
+ "action": action,
89
+ "status": "rejected",
90
+ "error": error,
91
+ "readiness": self.readiness(context.env),
92
+ "liveExecution": self.liveExecution,
93
+ "createdAt": context.createdAt,
94
+ }
95
+
96
+ def accepted(
97
+ self,
98
+ action: str,
99
+ payload: dict[str, Any],
100
+ context: PayRailAdapterContext,
101
+ *,
102
+ status: str = "prepared",
103
+ providerPrefix: str | None = None,
104
+ extra: dict[str, Any] | None = None,
105
+ ) -> dict[str, Any]:
106
+ providerRef = stableId(providerPrefix or self.adapterId, {"action": action, "payload": payload})
107
+ return {
108
+ "ok": True,
109
+ "adapterId": self.adapterId,
110
+ "railId": self.railId,
111
+ "action": action,
112
+ "status": status,
113
+ "providerRef": providerRef,
114
+ "readiness": self.readiness(context.env),
115
+ "liveExecution": self.liveExecution,
116
+ "createdAt": context.createdAt,
117
+ **(extra or {}),
118
+ }
119
+
120
+
121
+ class PicuxLedgerAdapter(PayRailAdapter):
122
+ adapterId = "picuxLedgerAdapter"
123
+ railId = "picuxLedger"
124
+ status = "local"
125
+ mode = "execute"
126
+ capabilities = ("challenge.create", "challenge.verify", "settlement.prepare", "settlement.execute", "session.consume", "escrow.test")
127
+
128
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
129
+ normalized = _action(action)
130
+ if normalized in {"challenge.create", "preparechallenge"}:
131
+ challenge = payload.get("challenge", payload) if isinstance(payload.get("challenge", payload), dict) else {}
132
+ challengeId = str(challenge.get("challengeId", "") or stableId("paychal", challenge))
133
+ return self.accepted(
134
+ "challenge.create",
135
+ challenge,
136
+ context,
137
+ providerPrefix="local_chal",
138
+ extra={
139
+ "headers": {
140
+ "WWW-Authenticate": f'Payment realm="picux", rail="picuxLedger", challenge="{challengeId}"',
141
+ "X-Picux-Payment-Challenge": challengeId,
142
+ },
143
+ "credentialMode": "localSignature",
144
+ },
145
+ )
146
+ if normalized in {"challenge.verify", "verifychallenge"}:
147
+ challenge = payload.get("challenge", {}) if isinstance(payload.get("challenge"), dict) else {}
148
+ credential = payload.get("credential", payload) if isinstance(payload.get("credential", payload), dict) else {}
149
+ expected = stableId(
150
+ "paysig",
151
+ {
152
+ "challengeId": str(challenge.get("challengeId", credential.get("challengeId", "")) or ""),
153
+ "railId": "picuxLedger",
154
+ "payer": credential.get("payer", {}) if isinstance(credential.get("payer"), dict) else {},
155
+ },
156
+ )
157
+ if str(credential.get("signature", "") or "") != expected:
158
+ return {**self.accepted("challenge.verify", payload, context, status="rejected"), "ok": False, "errors": ["signatureInvalid"]}
159
+ return self.accepted("challenge.verify", payload, context, status="verified", providerPrefix="local_verify")
160
+ if normalized in {"settlement.prepare", "preparesettlement"}:
161
+ instruction = payload.get("instruction", payload) if isinstance(payload.get("instruction", payload), dict) else {}
162
+ errors = instruction.get("errors", []) if isinstance(instruction.get("errors"), list) else []
163
+ status = "accepted" if not errors and str(instruction.get("status", "") or "") != "rejected" else "rejected"
164
+ return self.accepted("settlement.prepare", instruction, context, status=status, providerPrefix="local_settle")
165
+ if normalized in {"settlement.execute", "executesettlement", "settle"}:
166
+ instruction = payload.get("instruction", payload) if isinstance(payload.get("instruction", payload), dict) else {}
167
+ return self.accepted("settlement.execute", instruction, context, status="settled", providerPrefix="local_settle")
168
+ if normalized in {"session.consume", "consumesession"}:
169
+ return self.accepted("session.consume", payload, context, status="recorded", providerPrefix="local_session")
170
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
171
+
172
+
173
+ class X402VerifierAdapter(PayRailAdapter):
174
+ adapterId = "x402Verifier"
175
+ railId = "x402"
176
+ status = "contract"
177
+ mode = "verify"
178
+ capabilities = ("challenge.create", "challenge.verify", "facilitator.prepare")
179
+ requiredEnv = ("PICUX_X402_FACILITATOR_URL",)
180
+ envAliases = {"PICUX_X402_FACILITATOR_URL": ("X402_FACILITATOR_URL",)}
181
+
182
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
183
+ normalized = _action(action)
184
+ readiness = self.readiness(context.env)
185
+ if not readiness["configured"]:
186
+ return self.blocked(action, context, readiness)
187
+ challenge = payload.get("challenge", payload) if isinstance(payload.get("challenge", payload), dict) else {}
188
+ challengeId = str(challenge.get("challengeId", payload.get("challengeId", "")) or stableId("x402chal", challenge))
189
+ resource = challenge.get("resource", payload.get("resource", {})) if isinstance(challenge.get("resource", payload.get("resource", {})), dict) else {}
190
+ amount = challenge.get("amount", payload.get("amount", {})) if isinstance(challenge.get("amount", payload.get("amount", {})), dict) else {}
191
+ network = str(payload.get("network", "base") or "base")
192
+ if normalized in {"challenge.create", "preparechallenge", "facilitator.prepare"}:
193
+ return self.accepted(
194
+ "challenge.create",
195
+ challenge,
196
+ context,
197
+ providerPrefix="x402_chal",
198
+ extra={
199
+ "network": network,
200
+ "paymentScheme": "exact",
201
+ "facilitator": {"env": "PICUX_X402_FACILITATOR_URL"},
202
+ "challenge": {
203
+ "x402Version": "1",
204
+ "challengeId": challengeId,
205
+ "resource": resource,
206
+ "amount": amount,
207
+ "payTo": _payTo(challenge),
208
+ },
209
+ "headers": {
210
+ "WWW-Authenticate": f'Payment realm="picux", rail="x402", network="{network}", challenge="{challengeId}"',
211
+ "X-Picux-Payment-Challenge": challengeId,
212
+ },
213
+ "retry": {
214
+ "headers": {
215
+ "X-PAYMENT": "<base64url-encoded-x402-payment-payload>",
216
+ "X-Picux-Payment-Challenge": challengeId,
217
+ }
218
+ },
219
+ },
220
+ )
221
+ if normalized in {"challenge.verify", "verifychallenge"}:
222
+ credential = payload.get("credential", payload) if isinstance(payload.get("credential", payload), dict) else {}
223
+ headers = payload.get("headers", {}) if isinstance(payload.get("headers"), dict) else {}
224
+ xPayment = str(credential.get("xPayment", headers.get("X-PAYMENT", headers.get("x-payment", ""))) or "")
225
+ if not xPayment:
226
+ return {
227
+ **self.accepted("challenge.verify", payload, context, status="rejected", providerPrefix="x402_verify"),
228
+ "ok": False,
229
+ "errors": ["missing:X-PAYMENT"],
230
+ }
231
+ return self.accepted(
232
+ "challenge.verify",
233
+ {"challengeId": challengeId, "xPaymentHash": stableId("xpay", {"xPayment": xPayment})},
234
+ context,
235
+ status="readyForFacilitator",
236
+ providerPrefix="x402_verify",
237
+ extra={"facilitator": {"env": "PICUX_X402_FACILITATOR_URL"}, "verifiedBy": "externalFacilitator"},
238
+ )
239
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
240
+
241
+
242
+ class MppSessionAdapter(PayRailAdapter):
243
+ adapterId = "mppSessionAdapter"
244
+ railId = "mpp"
245
+ status = "contract"
246
+ mode = "session"
247
+ capabilities = ("session.authorize", "session.consume", "session.close")
248
+ requiredEnv = ("PICUX_MPP_ISSUER",)
249
+ envAliases = {"PICUX_MPP_ISSUER": ("MPP_ISSUER",)}
250
+
251
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
252
+ readiness = self.readiness(context.env)
253
+ if not readiness["configured"]:
254
+ return self.blocked(action, context, readiness)
255
+ normalized = _action(action)
256
+ session = payload.get("session", payload) if isinstance(payload.get("session", payload), dict) else {}
257
+ sessionId = str(session.get("sessionId", payload.get("sessionId", "")) or stableId("mppsess", session))
258
+ if normalized in {"session.authorize", "authorizesession"}:
259
+ return self.accepted(
260
+ "session.authorize",
261
+ session,
262
+ context,
263
+ status="authorized",
264
+ providerPrefix="mpp_auth",
265
+ extra={
266
+ "headers": {"Payment-Session": sessionId, "Payment-Auth": f'MPP session="{sessionId}", issuer="PICUX_MPP_ISSUER"'},
267
+ "sessionId": sessionId,
268
+ },
269
+ )
270
+ if normalized in {"session.consume", "consumesession"}:
271
+ return self.accepted("session.consume", session, context, status="recorded", providerPrefix="mpp_use", extra={"sessionId": sessionId})
272
+ if normalized in {"session.close", "closesession"}:
273
+ return self.accepted("session.close", session, context, status="closed", providerPrefix="mpp_close", extra={"sessionId": sessionId})
274
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
275
+
276
+
277
+ class StripeSptAdapter(PayRailAdapter):
278
+ adapterId = "stripeSptAdapter"
279
+ railId = "stripeSpt"
280
+ status = "contract"
281
+ mode = "execute"
282
+ capabilities = ("token.prepare", "fiat.authorize", "fiat.capture")
283
+ requiredEnv = ("STRIPE_SECRET_KEY",)
284
+
285
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
286
+ readiness = self.readiness(context.env)
287
+ if not readiness["configured"]:
288
+ return self.blocked(action, context, readiness)
289
+ normalized = _action(action)
290
+ instruction = payload.get("instruction", payload) if isinstance(payload.get("instruction", payload), dict) else {}
291
+ if normalized in {"token.prepare", "preparetoken", "settlement.prepare", "preparesettlement", "fiat.authorize"}:
292
+ amount = instruction.get("amount", payload.get("amount", {})) if isinstance(instruction.get("amount", payload.get("amount", {})), dict) else {}
293
+ return self.accepted(
294
+ "token.prepare",
295
+ instruction,
296
+ context,
297
+ status="prepared",
298
+ providerPrefix="stripe_spt",
299
+ extra={
300
+ "sharedPaymentTokenRequest": {
301
+ "merchant": str(instruction.get("payeeId", payload.get("merchantId", "")) or ""),
302
+ "customer": str(instruction.get("payerId", payload.get("customerId", "")) or ""),
303
+ "amount": amount,
304
+ "idempotencyKey": str(instruction.get("idempotencyKey", stableId("stripe_idem", instruction)) or ""),
305
+ "captureMode": "manual",
306
+ },
307
+ "provider": {"env": "STRIPE_SECRET_KEY"},
308
+ },
309
+ )
310
+ if normalized in {"fiat.capture", "capture"}:
311
+ return self.accepted("fiat.capture", instruction, context, status="captured", providerPrefix="stripe_capture", extra={"provider": {"env": "STRIPE_SECRET_KEY"}})
312
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
313
+
314
+
315
+ class SolanaEscrowAdapter(PayRailAdapter):
316
+ adapterId = "solanaEscrowAdapter"
317
+ railId = "solanaPay"
318
+ status = "planned"
319
+ mode = "escrow"
320
+ capabilities = ("mission.initialize", "mission.settle", "mission.abort")
321
+ requiredEnv = ("PICUX_SOLANA_RPC_URL", "PICUX_SOLANA_PROGRAM_ID")
322
+ envAliases = {
323
+ "PICUX_SOLANA_RPC_URL": ("SOLANA_RPC_URL",),
324
+ "PICUX_SOLANA_PROGRAM_ID": ("SOLANA_PROGRAM_ID", "PICUX_SOLANA_PUB_KEY", "SOLANA_PUB_KEY"),
325
+ "PICUX_SOLANA_APP_ID": ("SOLANA_APP_ID",),
326
+ }
327
+
328
+ def readiness(self, env: Mapping[str, str]) -> dict[str, Any]:
329
+ rpcKey = self.envKey(env, "PICUX_SOLANA_RPC_URL")
330
+ programKey = _firstEnv(env, ("PICUX_SOLANA_PROGRAM_ID", "SOLANA_PROGRAM_ID"))
331
+ recipientKey = _firstEnv(env, ("PICUX_SOLANA_PUB_KEY", "SOLANA_PUB_KEY"))
332
+ appKey = _firstEnv(env, ("PICUX_SOLANA_APP_ID", "SOLANA_APP_ID"))
333
+ missing = []
334
+ if not rpcKey:
335
+ missing.append("PICUX_SOLANA_RPC_URL")
336
+ if not programKey and not recipientKey:
337
+ missing.append("PICUX_SOLANA_PROGRAM_ID")
338
+ mode = "escrowProgram" if programKey else "paymentIntent"
339
+ return {
340
+ "configured": not missing,
341
+ "missingEnv": missing,
342
+ "resolvedEnv": {
343
+ **({"PICUX_SOLANA_RPC_URL": rpcKey} if rpcKey else {}),
344
+ **({"PICUX_SOLANA_PROGRAM_ID": programKey} if programKey else {}),
345
+ **({"PICUX_SOLANA_PUB_KEY": recipientKey} if recipientKey else {}),
346
+ **({"PICUX_SOLANA_APP_ID": appKey} if appKey else {}),
347
+ },
348
+ "mode": mode if not missing else "prepare",
349
+ }
350
+
351
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
352
+ readiness = self.readiness(context.env)
353
+ if not readiness["configured"]:
354
+ return self.blocked(action, context, readiness)
355
+ normalized = _action(action)
356
+ mission = payload.get("mission", payload.get("instruction", payload)) if isinstance(payload.get("mission", payload.get("instruction", payload)), dict) else {}
357
+ missionId = str(mission.get("missionId", mission.get("settlementId", "")) or stableId("solmission", mission))
358
+ if normalized in {"mission.initialize", "initializemission", "settlement.prepare", "preparesettlement"}:
359
+ readiness = self.readiness(context.env)
360
+ programKey = str(readiness.get("resolvedEnv", {}).get("PICUX_SOLANA_PROGRAM_ID", "") or "")
361
+ recipientKey = str(readiness.get("resolvedEnv", {}).get("PICUX_SOLANA_PUB_KEY", "") or "")
362
+ appKey = str(readiness.get("resolvedEnv", {}).get("PICUX_SOLANA_APP_ID", "") or "")
363
+ method = "initialize_mission" if programKey else "solana_pay_transfer"
364
+ status = "transactionPreflighted" if self._liveRequested(payload, mission, context.env) else "transactionPrepared"
365
+ extra = {
366
+ "chain": "solana",
367
+ "program": {"env": programKey} if programKey else {},
368
+ "recipient": {"env": recipientKey} if recipientKey else {},
369
+ "app": {"env": appKey} if appKey else {},
370
+ "transactionIntent": {
371
+ "method": method,
372
+ "missionId": missionId,
373
+ "pdaSeeds": ["picux", missionId, str(mission.get("payerId", mission.get("agent", "")) or "")],
374
+ "amount": mission.get("amount", {}),
375
+ "merchant": str(mission.get("payeeId", mission.get("merchant", "")) or ""),
376
+ "appIdEnv": appKey,
377
+ },
378
+ }
379
+ extra = self._withSolanaRpc(extra, payload, mission, context.env)
380
+ status = str(extra.pop("liveStatus", status) or status)
381
+ result = self.accepted(
382
+ "mission.initialize",
383
+ mission,
384
+ context,
385
+ status=status,
386
+ providerPrefix="solana_mission",
387
+ extra=extra,
388
+ )
389
+ return self._rpcGuard(result)
390
+ if normalized in {"mission.settle", "settlemission", "settlement.execute", "executesettlement"}:
391
+ status = "transactionPreflighted" if self._liveRequested(payload, mission, context.env) else "transactionPrepared"
392
+ extra = self._withSolanaRpc({"chain": "solana", "transactionIntent": {"method": "settle_mission", "missionId": missionId}}, payload, mission, context.env)
393
+ status = str(extra.pop("liveStatus", status) or status)
394
+ return self._rpcGuard(self.accepted("mission.settle", mission, context, status=status, providerPrefix="solana_settle", extra=extra))
395
+ if normalized in {"mission.abort", "abortmission", "refund"}:
396
+ status = "transactionPreflighted" if self._liveRequested(payload, mission, context.env) else "transactionPrepared"
397
+ extra = self._withSolanaRpc({"chain": "solana", "transactionIntent": {"method": "abort_mission", "missionId": missionId}}, payload, mission, context.env)
398
+ status = str(extra.pop("liveStatus", status) or status)
399
+ return self._rpcGuard(self.accepted("mission.abort", mission, context, status=status, providerPrefix="solana_abort", extra=extra))
400
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
401
+
402
+ def _withSolanaRpc(self, extra: dict[str, Any], payload: dict[str, Any], mission: dict[str, Any], env: Mapping[str, str]) -> dict[str, Any]:
403
+ if not self._liveRequested(payload, mission, env):
404
+ return extra
405
+ rpcUrl = str(env.get(self.envKey(env, "PICUX_SOLANA_RPC_URL"), "") or env.get("PICUX_SOLANA_RPC_URL", "") or env.get("SOLANA_RPC_URL", "") or "")
406
+ if not rpcUrl:
407
+ return {**extra, "rpc": {"attempted": True, "ok": False, "error": "missingRpcUrl"}}
408
+ preflight = _solanaRpc(rpcUrl, "getLatestBlockhash", [{"commitment": "confirmed"}])
409
+ signed = self._signedTransaction(payload, mission)
410
+ if not signed:
411
+ return {**extra, "rpc": preflight}
412
+ send = _solanaRpc(
413
+ rpcUrl,
414
+ "sendTransaction",
415
+ [signed, {"encoding": "base64", "skipPreflight": False, "preflightCommitment": "confirmed"}],
416
+ )
417
+ signature = str(send.get("signature", "") or send.get("result", "") or "")
418
+ confirm = _solanaRpc(rpcUrl, "getSignatureStatuses", [[signature], {"searchTransactionHistory": True}]) if signature else {}
419
+ confirmed = bool(confirm.get("confirmed", False))
420
+ return {
421
+ **extra,
422
+ "liveStatus": "transactionConfirmed" if confirmed else ("transactionSubmitted" if send.get("ok") else "transactionRejected"),
423
+ "rpc": {
424
+ "attempted": True,
425
+ "ok": bool(preflight.get("ok") and send.get("ok") and (not confirm or confirm.get("ok"))),
426
+ "preflight": preflight,
427
+ "send": send,
428
+ "confirm": confirm,
429
+ "signature": signature,
430
+ "confirmed": confirmed,
431
+ },
432
+ }
433
+
434
+ @staticmethod
435
+ def _liveRequested(payload: dict[str, Any], mission: dict[str, Any], env: Mapping[str, str]) -> bool:
436
+ return _truthy(payload.get("live", payload.get("execute", mission.get("live", mission.get("execute", ""))))) or _truthy(env.get("PICUX_SOLANA_LIVE_RPC", env.get("SOLANA_LIVE_RPC", "")))
437
+
438
+ @staticmethod
439
+ def _signedTransaction(payload: dict[str, Any], mission: dict[str, Any]) -> str:
440
+ tx = payload.get("signedTransaction", mission.get("signedTransaction", ""))
441
+ transaction = payload.get("transaction", mission.get("transaction", {}))
442
+ if not tx and isinstance(transaction, dict):
443
+ tx = transaction.get("signed", transaction.get("base64", transaction.get("serialized", "")))
444
+ return str(tx or "").strip()
445
+
446
+ @staticmethod
447
+ def _rpcGuard(result: dict[str, Any]) -> dict[str, Any]:
448
+ rpc = result.get("rpc", {}) if isinstance(result.get("rpc"), dict) else {}
449
+ if rpc and not rpc.get("ok"):
450
+ return {**result, "ok": False, "status": "ioError", "error": "solanaRpcUnavailable"}
451
+ return result
452
+
453
+
454
+ class BaseEscrowAdapter(PayRailAdapter):
455
+ adapterId = "baseEscrowAdapter"
456
+ railId = "baseUsdc"
457
+ status = "planned"
458
+ mode = "escrow"
459
+ capabilities = ("mission.initialize", "mission.settle", "mission.abort")
460
+ requiredEnv = ("PICUX_BASE_RPC_URL", "PICUX_BASE_ESCROW_ADDRESS")
461
+ envAliases = {
462
+ "PICUX_BASE_RPC_URL": ("BASE_RPC_URL",),
463
+ "PICUX_BASE_ESCROW_ADDRESS": ("BASE_ESCROW_ADDRESS",),
464
+ }
465
+
466
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
467
+ readiness = self.readiness(context.env)
468
+ if not readiness["configured"]:
469
+ return self.blocked(action, context, readiness)
470
+ normalized = _action(action)
471
+ mission = payload.get("mission", payload.get("instruction", payload)) if isinstance(payload.get("mission", payload.get("instruction", payload)), dict) else {}
472
+ missionId = str(mission.get("missionId", mission.get("settlementId", "")) or stableId("basemission", mission))
473
+ if normalized in {"mission.initialize", "initializemission", "settlement.prepare", "preparesettlement"}:
474
+ return self.accepted(
475
+ "mission.initialize",
476
+ mission,
477
+ context,
478
+ status="transactionPrepared",
479
+ providerPrefix="base_mission",
480
+ extra={
481
+ "chain": "base",
482
+ "contract": {"env": "PICUX_BASE_ESCROW_ADDRESS"},
483
+ "transactionIntent": {
484
+ "method": "initializeMission",
485
+ "missionId": missionId,
486
+ "amount": mission.get("amount", {}),
487
+ "merchant": str(mission.get("payeeId", mission.get("merchant", "")) or ""),
488
+ },
489
+ },
490
+ )
491
+ if normalized in {"mission.settle", "settlemission", "settlement.execute", "executesettlement"}:
492
+ return self.accepted("mission.settle", mission, context, status="transactionPrepared", providerPrefix="base_settle", extra={"chain": "base", "transactionIntent": {"method": "settleMission", "missionId": missionId}})
493
+ if normalized in {"mission.abort", "abortmission", "refund"}:
494
+ return self.accepted("mission.abort", mission, context, status="transactionPrepared", providerPrefix="base_abort", extra={"chain": "base", "transactionIntent": {"method": "abortMission", "missionId": missionId}})
495
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
496
+
497
+
498
+ class L402Adapter(PayRailAdapter):
499
+ adapterId = "l402Adapter"
500
+ railId = "l402"
501
+ status = "planned"
502
+ mode = "verify"
503
+ capabilities = ("macaroon.issue", "invoice.verify", "preimage.redeem")
504
+ requiredEnv = ("PICUX_L402_NODE_URL",)
505
+ envAliases = {"PICUX_L402_NODE_URL": ("L402_NODE_URL",)}
506
+
507
+ def invoke(self, action: str, payload: dict[str, Any], context: PayRailAdapterContext) -> dict[str, Any]:
508
+ readiness = self.readiness(context.env)
509
+ if not readiness["configured"]:
510
+ return self.blocked(action, context, readiness)
511
+ normalized = _action(action)
512
+ challenge = payload.get("challenge", payload) if isinstance(payload.get("challenge", payload), dict) else {}
513
+ challengeId = str(challenge.get("challengeId", payload.get("challengeId", "")) or stableId("l402chal", challenge))
514
+ if normalized in {"macaroon.issue", "challenge.create", "preparechallenge"}:
515
+ macaroonRef = stableId("macaroon", {"challengeId": challengeId, "resource": challenge.get("resource", {})})
516
+ invoiceRef = stableId("invoice", {"challengeId": challengeId, "amount": challenge.get("amount", {})})
517
+ return self.accepted(
518
+ "macaroon.issue",
519
+ challenge,
520
+ context,
521
+ providerPrefix="l402_issue",
522
+ extra={
523
+ "headers": {"WWW-Authenticate": f'L402 macaroon="{macaroonRef}", invoice="{invoiceRef}"'},
524
+ "macaroonRef": macaroonRef,
525
+ "invoiceRef": invoiceRef,
526
+ "provider": {"env": "PICUX_L402_NODE_URL"},
527
+ },
528
+ )
529
+ if normalized in {"invoice.verify", "preimage.redeem", "challenge.verify", "verifychallenge"}:
530
+ credential = payload.get("credential", payload) if isinstance(payload.get("credential", payload), dict) else {}
531
+ preimage = str(credential.get("preimage", payload.get("preimage", "")) or "")
532
+ if not preimage:
533
+ return {**self.accepted("invoice.verify", payload, context, status="rejected", providerPrefix="l402_verify"), "ok": False, "errors": ["missing:preimage"]}
534
+ return self.accepted("invoice.verify", {"challengeId": challengeId, "preimageHash": stableId("preimage", {"preimage": preimage})}, context, status="verified", providerPrefix="l402_verify")
535
+ return self.unsupported(action, context, f"unsupportedAction:{action}")
536
+
537
+
538
+ def defaultAdapters() -> list[PayRailAdapter]:
539
+ return [
540
+ PicuxLedgerAdapter(),
541
+ X402VerifierAdapter(),
542
+ MppSessionAdapter(),
543
+ StripeSptAdapter(),
544
+ SolanaEscrowAdapter(),
545
+ BaseEscrowAdapter(),
546
+ L402Adapter(),
547
+ ]
548
+
549
+
550
+ def _action(value: str) -> str:
551
+ return str(value or "").replace("_", ".").replace("-", ".").strip().lower()
552
+
553
+
554
+ def _payTo(challenge: dict[str, Any]) -> str:
555
+ payee = challenge.get("payee", {}) if isinstance(challenge.get("payee"), dict) else {}
556
+ return str(payee.get("walletAddress", payee.get("entityId", "")) or "")
557
+
558
+
559
+ def _firstEnv(env: Mapping[str, str], keys: tuple[str, ...]) -> str:
560
+ return next((key for key in keys if str(env.get(key, "") or "").strip()), "")
561
+
562
+
563
+ def _truthy(value: Any) -> bool:
564
+ return str(value or "").strip().lower() in {"1", "true", "yes", "y", "live", "execute"}
565
+
566
+
567
+ def _solanaRpc(rpcUrl: str, method: str, params: list[Any] | None = None) -> dict[str, Any]:
568
+ body = json.dumps({"jsonrpc": "2.0", "id": "picux-pay-preflight", "method": method, "params": params or []}, ensure_ascii=True).encode("utf-8")
569
+ req = request.Request(
570
+ rpcUrl,
571
+ data=body,
572
+ method="POST",
573
+ headers={"Accept": "application/json", "Content-Type": "application/json"},
574
+ )
575
+ try:
576
+ with request.urlopen(req, timeout=15) as response:
577
+ raw = response.read()
578
+ decoded = json.loads(raw.decode("utf-8") or "{}")
579
+ result = decoded.get("result", {}) if isinstance(decoded, dict) else {}
580
+ value = result.get("value", {}) if isinstance(result, dict) else {}
581
+ signature = result if isinstance(result, str) else ""
582
+ statuses = value if isinstance(value, list) else []
583
+ firstStatus = statuses[0] if statuses and isinstance(statuses[0], dict) else {}
584
+ return {
585
+ "attempted": True,
586
+ "ok": "error" not in decoded,
587
+ "method": method,
588
+ "endpoint": _safeRpcUrl(rpcUrl),
589
+ "providerStatus": int(response.status),
590
+ "result": result,
591
+ "signature": signature,
592
+ "confirmed": str(firstStatus.get("confirmationStatus", "") or "").lower() in {"confirmed", "finalized"} or bool(firstStatus.get("confirmations") is None and firstStatus),
593
+ "blockhash": str(value.get("blockhash", "") or "") if isinstance(value, dict) else "",
594
+ "lastValidBlockHeight": value.get("lastValidBlockHeight", "") if isinstance(value, dict) else "",
595
+ "error": decoded.get("error", {}) if isinstance(decoded, dict) else {},
596
+ }
597
+ except error.HTTPError as exc:
598
+ return {"attempted": True, "ok": False, "method": method, "endpoint": _safeRpcUrl(rpcUrl), "providerStatus": int(exc.code), "error": exc.read().decode("utf-8", errors="replace")[:500]}
599
+ except Exception as exc:
600
+ return {"attempted": True, "ok": False, "method": method, "endpoint": _safeRpcUrl(rpcUrl), "providerStatus": 0, "error": str(exc)}
601
+
602
+
603
+ def _safeRpcUrl(rpcUrl: str) -> str:
604
+ parsed = urlparse(str(rpcUrl or ""))
605
+ if not parsed.scheme:
606
+ return ""
607
+ return f"{parsed.scheme}://{parsed.netloc}{parsed.path}"