@stelis/say-ur-intent 0.0.0 → 0.0.2

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 (234) hide show
  1. package/README.md +4 -39
  2. package/dist/adapters/adapterLifecycleValidators.js +7 -0
  3. package/dist/adapters/adapterPromptSurfaces.js +71 -0
  4. package/dist/adapters/deepbook/deepbookHumanReviewProducer.js +175 -0
  5. package/dist/adapters/deepbook/deepbookQuotePolicy.js +112 -0
  6. package/dist/adapters/deepbook/deepbookReviewEvidence.js +507 -0
  7. package/dist/adapters/deepbook/deepbookReviewLifecycle.js +85 -0
  8. package/dist/adapters/deepbook/deepbookSwapIntent.js +79 -0
  9. package/dist/adapters/deepbook/deepbookTransactionMaterialProducer.js +269 -0
  10. package/dist/adapters/flowx/flowxSwapHumanReviewProducer.js +176 -0
  11. package/dist/adapters/flowx/flowxSwapIntent.js +79 -0
  12. package/dist/adapters/flowx/flowxSwapQuotePolicy.js +104 -0
  13. package/dist/adapters/flowx/flowxSwapReviewEvidence.js +468 -0
  14. package/dist/adapters/flowx/flowxSwapReviewLifecycle.js +85 -0
  15. package/dist/adapters/flowx/flowxSwapTransactionMaterialProducer.js +362 -0
  16. package/dist/adapters/intentPlanFactories.js +59 -0
  17. package/dist/adapters/reviewAdapters.js +81 -0
  18. package/dist/core/action/adapterLifecycleValidation.js +12 -0
  19. package/dist/core/action/forbiddenFields.js +43 -0
  20. package/dist/core/action/humanReadableReviewEvidence.js +203 -0
  21. package/dist/core/action/humanReadableReviewProjectionVerifier.js +29 -0
  22. package/dist/core/action/ptbVisualizationProducer.js +66 -0
  23. package/dist/core/action/reviewCheckResults.js +6 -0
  24. package/dist/core/action/reviewStateValidation.js +11 -0
  25. package/dist/core/action/reviewTimeSimulationEvidence.js +471 -0
  26. package/dist/core/action/schemas.js +529 -0
  27. package/dist/core/action/signableAdapterContract.js +993 -0
  28. package/dist/core/action/swapHumanReadableReviewProjection.js +124 -0
  29. package/dist/core/action/swapQuotePolicyEvidence.js +278 -0
  30. package/dist/core/action/transactionObjectOwnershipEvidence.js +247 -0
  31. package/dist/core/action/transactionObjectOwnershipProducer.js +329 -0
  32. package/dist/core/action/types.js +35 -0
  33. package/dist/core/action/walletReviewContractAssembler.js +282 -0
  34. package/dist/core/activity/activityStore.js +15 -0
  35. package/dist/core/activity/localDataService.js +258 -0
  36. package/dist/core/activity/localDataTypes.js +11 -0
  37. package/dist/core/activity/localDataValidation.js +396 -0
  38. package/dist/core/activity/schemaVersion.js +1 -0
  39. package/dist/core/activity/sqliteActivityStore.js +820 -0
  40. package/dist/core/activity/sqliteActivityStoreRows.js +430 -0
  41. package/dist/core/activity/sqliteActivityStoreSchema.js +258 -0
  42. package/dist/core/activity/sqliteActivityStoreTypes.js +5 -0
  43. package/dist/core/activity/suiFunctionTarget.js +43 -0
  44. package/dist/core/activity/transactionActivityAccountEffects.js +189 -0
  45. package/dist/core/activity/transactionActivityAnalysis.js +295 -0
  46. package/dist/core/activity/transactionActivityClassifier.js +306 -0
  47. package/dist/core/activity/transactionActivityDetails.js +229 -0
  48. package/dist/core/activity/transactionActivityProtocolRules.js +218 -0
  49. package/dist/core/activity/transactionActivityScanPolicy.js +170 -0
  50. package/dist/core/activity/transactionActivityService.js +379 -0
  51. package/dist/core/activity/transactionActivityTypes.js +18 -0
  52. package/dist/core/eventlog/sink.js +35 -0
  53. package/dist/core/evidence/settlementFamilies.js +87 -0
  54. package/dist/core/evidence/userAnswerUse.js +1 -0
  55. package/dist/core/numeric/rawU64.js +63 -0
  56. package/dist/core/preferences/preferencesStore.js +26 -0
  57. package/dist/core/preferences/sqlitePreferencesRepository.js +136 -0
  58. package/dist/core/proposal/externalProposalReview.js +347 -0
  59. package/dist/core/proposal/schemas.js +208 -0
  60. package/dist/core/proposal/types.js +35 -0
  61. package/dist/core/read/amounts.js +14 -0
  62. package/dist/core/read/coinMetadata.js +60 -0
  63. package/dist/core/read/deepbookRawQuoteClient.js +86 -0
  64. package/dist/core/read/deepbookReadHelpers.js +265 -0
  65. package/dist/core/read/deepbookRegistry.js +133 -0
  66. package/dist/core/read/flowxQuoteClient.js +117 -0
  67. package/dist/core/read/flowxReadHelpers.js +145 -0
  68. package/dist/core/read/flowxRegistry.js +174 -0
  69. package/dist/core/read/intentEvidenceResponseFormatting.js +228 -0
  70. package/dist/core/read/readResponseGuidance.js +451 -0
  71. package/dist/core/read/readService.js +1164 -0
  72. package/dist/core/read/readServiceTypes.js +59 -0
  73. package/dist/core/read/settlementParityFormatting.js +82 -0
  74. package/dist/core/read/walletReadHelpers.js +99 -0
  75. package/dist/core/review/reviewChecks.js +54 -0
  76. package/dist/core/review/reviewComputation.js +38 -0
  77. package/dist/core/review/reviewComputationResult.js +87 -0
  78. package/dist/core/session/localSession.js +31 -0
  79. package/dist/core/session/privateReviewArtifacts.js +73 -0
  80. package/dist/core/session/sessionErrors.js +9 -0
  81. package/dist/core/session/sessionStore.js +821 -0
  82. package/dist/core/session/settingsSession.js +1 -0
  83. package/dist/core/session/settingsSessions.js +43 -0
  84. package/dist/core/session/status.js +86 -0
  85. package/dist/core/session/transactionMaterialStore.js +205 -0
  86. package/dist/core/session/wait.js +102 -0
  87. package/dist/core/session/walletIdentity.js +103 -0
  88. package/dist/core/session/walletIdentitySessions.js +189 -0
  89. package/dist/core/suiAddress.js +18 -0
  90. package/dist/core/suiEndpoint.js +72 -0
  91. package/dist/mcp/activeAccountResponse.js +24 -0
  92. package/dist/mcp/prompts.js +146 -0
  93. package/dist/mcp/registerTool.js +19 -0
  94. package/dist/mcp/resources.js +72 -0
  95. package/dist/mcp/responseGuidance.js +381 -0
  96. package/dist/mcp/result.js +17 -0
  97. package/dist/mcp/schemas.js +8 -0
  98. package/dist/mcp/server.js +30 -0
  99. package/dist/mcp/serverInfo.js +123 -0
  100. package/dist/mcp/toolErrors.js +105 -0
  101. package/dist/mcp/toolNames.js +50 -0
  102. package/dist/mcp/tools/account/index.js +44 -0
  103. package/dist/mcp/tools/action/prepareSuiActionReview.js +120 -0
  104. package/dist/mcp/tools/read/commonSchemas.js +43 -0
  105. package/dist/mcp/tools/read/deepbookReadTools.js +453 -0
  106. package/dist/mcp/tools/read/flowxReadTools.js +135 -0
  107. package/dist/mcp/tools/read/index.js +16 -0
  108. package/dist/mcp/tools/read/readToolHelpers.js +68 -0
  109. package/dist/mcp/tools/read/reviewActivityTools.js +176 -0
  110. package/dist/mcp/tools/read/serverStatusTools.js +103 -0
  111. package/dist/mcp/tools/read/transactionActivityOutput.js +300 -0
  112. package/dist/mcp/tools/read/transactionActivityTools.js +544 -0
  113. package/dist/mcp/tools/read/walletReadTools.js +733 -0
  114. package/dist/mcp/tools/session/executionResultTools.js +92 -0
  115. package/dist/mcp/tools/session/index.js +8 -0
  116. package/dist/mcp/tools/session/shared.js +79 -0
  117. package/dist/mcp/tools/session/statusTools.js +134 -0
  118. package/dist/mcp/tools/session/walletIdentityTools.js +119 -0
  119. package/dist/mcp/tools/settings/index.js +64 -0
  120. package/dist/review-app/analysis.css +1 -0
  121. package/dist/review-app/analysis.js +1 -0
  122. package/dist/review-app/arc-BjIacwQm.js +1 -0
  123. package/dist/review-app/architecture-U656AL7Q-aSB9x1OK.js +1 -0
  124. package/dist/review-app/architectureDiagram-VXUJARFQ-C5W6re2I.js +36 -0
  125. package/dist/review-app/array-BmXUUrU6.js +1 -0
  126. package/dist/review-app/blockDiagram-VD42YOAC-20MLNcUm.js +122 -0
  127. package/dist/review-app/c4Diagram-YG6GDRKO-BZXRrcck.js +10 -0
  128. package/dist/review-app/channel-lk2p_CUu.js +1 -0
  129. package/dist/review-app/chunk-4BX2VUAB-BPITOdjX.js +1 -0
  130. package/dist/review-app/chunk-55IACEB6-Dz-pyw5k.js +1 -0
  131. package/dist/review-app/chunk-76Q3JFCE-cK_X1P_l.js +1 -0
  132. package/dist/review-app/chunk-ABZYJK2D-Dt4W53JI.js +81 -0
  133. package/dist/review-app/chunk-ATLVNIR6-fZHLXURb.js +1 -0
  134. package/dist/review-app/chunk-B4BG7PRW-BbgcjusC.js +165 -0
  135. package/dist/review-app/chunk-BJD4TVEz.js +1 -0
  136. package/dist/review-app/chunk-CVBHYZKI-CViawAKX.js +1 -0
  137. package/dist/review-app/chunk-DI55MBZ5-C5aoul-d.js +220 -0
  138. package/dist/review-app/chunk-FMBD7UC4-Chxmw62A.js +15 -0
  139. package/dist/review-app/chunk-FPAJGGOC-DDHjQ09H.js +80 -0
  140. package/dist/review-app/chunk-FWNWRKHM-CVVQUptk.js +1 -0
  141. package/dist/review-app/chunk-HN2XXSSU-yzNpjaSZ.js +1 -0
  142. package/dist/review-app/chunk-JA3XYJ7Z-C5ZJdU01.js +70 -0
  143. package/dist/review-app/chunk-JZLCHNYA-BBST4Cnk.js +54 -0
  144. package/dist/review-app/chunk-LBM3YZW2-CdwAPuHr.js +1 -0
  145. package/dist/review-app/chunk-LHMN2FUI-BtB5uDcp.js +1 -0
  146. package/dist/review-app/chunk-O7ZBX7Z2-pxdK4Sa3.js +1 -0
  147. package/dist/review-app/chunk-QN33PNHL-CbVv3uGK.js +1 -0
  148. package/dist/review-app/chunk-QXUST7PY-DKM2-t2c.js +7 -0
  149. package/dist/review-app/chunk-QZHKN3VN-C5ni2pN_.js +1 -0
  150. package/dist/review-app/chunk-S3R3BYOJ-BWvOhDs0.js +2 -0
  151. package/dist/review-app/chunk-S6J4BHB3-D9Fk0YeD.js +1 -0
  152. package/dist/review-app/chunk-T53DSG4Q-C1qEyzyV.js +1 -0
  153. package/dist/review-app/chunk-TZMSLE5B-B--7eU69.js +1 -0
  154. package/dist/review-app/classDiagram-2ON5EDUG-DlL1m2bp.js +1 -0
  155. package/dist/review-app/classDiagram-v2-WZHVMYZB-FXRskT1j.js +1 -0
  156. package/dist/review-app/clone-BZZb7gpZ.js +1 -0
  157. package/dist/review-app/cose-bilkent-S5V4N54A-CRIb8XEO.js +1 -0
  158. package/dist/review-app/cytoscape.esm-C7jYqDP5.js +321 -0
  159. package/dist/review-app/dagre-6UL2VRFP-FNCAXbdE.js +4 -0
  160. package/dist/review-app/dagre-Be46QtUd.js +1 -0
  161. package/dist/review-app/defaultLocale-BaWNtAUL.js +1 -0
  162. package/dist/review-app/diagram-PSM6KHXK-ylLWjiNM.js +24 -0
  163. package/dist/review-app/diagram-QEK2KX5R-BCDcESxs.js +43 -0
  164. package/dist/review-app/diagram-S2PKOQOG-Vdrc-vrO.js +24 -0
  165. package/dist/review-app/dist-WPc74x_f.js +1 -0
  166. package/dist/review-app/erDiagram-Q2GNP2WA-E5ZsUbDF.js +60 -0
  167. package/dist/review-app/flatten-DHf9IeNI.js +1 -0
  168. package/dist/review-app/flowDiagram-NV44I4VS-DBSQuj6x.js +162 -0
  169. package/dist/review-app/ganttDiagram-LVOFAZNH-CKUOsqwl.js +267 -0
  170. package/dist/review-app/gitGraph-F6HP7TQM-DsAD6qK1.js +1 -0
  171. package/dist/review-app/gitGraphDiagram-NY62KEGX-BCeIMWdl.js +65 -0
  172. package/dist/review-app/graphlib-CiX5CXxR.js +1 -0
  173. package/dist/review-app/http-DMvwuuFk.js +1 -0
  174. package/dist/review-app/identity-DY8PXc6t.js +1 -0
  175. package/dist/review-app/info-NVLQJR56-Dlx1nZic.js +1 -0
  176. package/dist/review-app/infoDiagram-F6ZHWCRC-CAuANIrz.js +2 -0
  177. package/dist/review-app/init-BvqephKz.js +1 -0
  178. package/dist/review-app/journeyDiagram-XKPGCS4Q-C-Z9phnx.js +139 -0
  179. package/dist/review-app/kanban-definition-3W4ZIXB7-DufgZABq.js +89 -0
  180. package/dist/review-app/katex-B-Z-NXXN.js +257 -0
  181. package/dist/review-app/line-DiIv3Jgw.js +1 -0
  182. package/dist/review-app/linear-Cv-UPvo1.js +1 -0
  183. package/dist/review-app/math-kmyYrkHL.js +1 -0
  184. package/dist/review-app/mermaid-parser.core-DkwUYTPl.js +4 -0
  185. package/dist/review-app/mindmap-definition-VGOIOE7T-TM_CqdmV.js +68 -0
  186. package/dist/review-app/ordinal-BliTlkoG.js +1 -0
  187. package/dist/review-app/packet-BFZMPI3H-DqbnU92v.js +1 -0
  188. package/dist/review-app/path-AEo9W6mQ.js +1 -0
  189. package/dist/review-app/pie-7BOR55EZ-LJzaLkgr.js +1 -0
  190. package/dist/review-app/pieDiagram-ADFJNKIX-BAs8OfRS.js +30 -0
  191. package/dist/review-app/quadrantDiagram-AYHSOK5B-CyUDZP5S.js +7 -0
  192. package/dist/review-app/radar-NHE76QYJ-DBpHc8_Y.js +1 -0
  193. package/dist/review-app/reduce-B-HuPpdd.js +1 -0
  194. package/dist/review-app/requirementDiagram-UZGBJVZJ-BEHix78P.js +64 -0
  195. package/dist/review-app/review.css +1 -0
  196. package/dist/review-app/review.js +43 -0
  197. package/dist/review-app/sankeyDiagram-TZEHDZUN-B2bKbmsm.js +10 -0
  198. package/dist/review-app/sequenceDiagram-WL72ISMW-DVLOORFJ.js +145 -0
  199. package/dist/review-app/settings.css +1 -0
  200. package/dist/review-app/settings.js +1 -0
  201. package/dist/review-app/src-Buml7cM5.js +1 -0
  202. package/dist/review-app/stateDiagram-FKZM4ZOC-sFGGp2kV.js +1 -0
  203. package/dist/review-app/stateDiagram-v2-4FDKWEC3-BHfCF4dX.js +1 -0
  204. package/dist/review-app/timeline-definition-IT6M3QCI-BESnBijC.js +61 -0
  205. package/dist/review-app/treemap-KMMF4GRG-wnVLBDeQ.js +1 -0
  206. package/dist/review-app/walletStatus-CcojOdGy.js +7 -0
  207. package/dist/review-app/xychartDiagram-PRI3JC2R-BGWVfCx4.js +7 -0
  208. package/dist/review-server/assets.js +48 -0
  209. package/dist/review-server/html.js +66 -0
  210. package/dist/review-server/http.js +47 -0
  211. package/dist/review-server/middleware/hostOrigin.js +48 -0
  212. package/dist/review-server/middleware/reviewToken.js +7 -0
  213. package/dist/review-server/reviewServerPolicy.js +10 -0
  214. package/dist/review-server/server.js +568 -0
  215. package/dist/review-server/settingsApi.js +182 -0
  216. package/dist/review-server/walletIdentityResponse.js +13 -0
  217. package/dist/runtime/config.js +103 -0
  218. package/dist/runtime/localSettingsService.js +198 -0
  219. package/dist/runtime/logger.js +50 -0
  220. package/dist/runtime/reviewServerAcquire.js +128 -0
  221. package/dist/runtime/smokeMainnetRead.js +529 -0
  222. package/dist/runtime/smokeMainnetReadAssertions.js +308 -0
  223. package/dist/runtime/start.js +295 -0
  224. package/dist/runtime/suiEndpoint.js +97 -0
  225. package/dist/runtime/suiTransactionGraphqlMapping.js +200 -0
  226. package/dist/runtime/suiTransactionGraphqlQueries.js +231 -0
  227. package/dist/runtime/suiTransactionGraphqlSource.js +148 -0
  228. package/docs/AGENT_BEHAVIOR.md +1 -1
  229. package/docs/AGENT_DEVELOPMENT_POLICY.md +20 -0
  230. package/docs/FRONTEND_POLICY.md +4 -3
  231. package/docs/MCP_SETUP.md +59 -7
  232. package/docs/MCP_TOOLS.md +1 -1
  233. package/docs/SDK_API.md +5 -1
  234. package/package.json +3 -2
@@ -0,0 +1,993 @@
1
+ import { z } from "zod";
2
+ import { normalizeCoinType } from "../read/coinMetadata.js";
3
+ import { SUI_COIN_TYPE } from "../read/walletReadHelpers.js";
4
+ import { makeCanonicalRawU64StringSchema } from "../numeric/rawU64.js";
5
+ import { suiAddressStringSchema, suiTransactionDigestSchema } from "../suiAddress.js";
6
+ export const WALLET_REVIEW_ADAPTER_CONTRACT_VERSION = "wallet-review-adapter-contract-alpha-2026-06-02";
7
+ export const PTB_VISUALIZATION_CONTRACT_VERSION = "ptb-visualization-contract-alpha-2026-05-25";
8
+ export const WALLET_REVIEW_REQUIRED_HUMAN_FIELDS = [
9
+ "proposedAction",
10
+ "assetFlow",
11
+ "recipients",
12
+ "targets",
13
+ "evidenceUsed",
14
+ "missingEvidence",
15
+ "requiredUserChoices",
16
+ "unsupportedClaims",
17
+ "freshness",
18
+ "blockingChecks"
19
+ ];
20
+ export const WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS = [
21
+ "effects",
22
+ "balanceChanges",
23
+ "objectTypes",
24
+ "transaction"
25
+ ];
26
+ export const WALLET_REVIEW_REQUIRED_PROHIBITED_OUTPUTS = [
27
+ "transaction_bytes",
28
+ "serialized_transaction",
29
+ "wallet_signature_request",
30
+ "private_key_material",
31
+ "wallet_authorization",
32
+ "signing_data",
33
+ "signing_readiness",
34
+ "payment_execution_readiness"
35
+ ];
36
+ export const PTB_VISUALIZATION_REQUIRED_UNSUPPORTED_USES = [
37
+ "transaction_building_input",
38
+ "wallet_authorization",
39
+ "signing_data",
40
+ "signing_readiness",
41
+ "payment_execution_readiness",
42
+ "route_recommendation"
43
+ ];
44
+ export const SUI_GAS_COIN_TYPE = SUI_COIN_TYPE;
45
+ export const SUI_GAS_RAW_UNIT = "MIST";
46
+ const EXPIRY_TIMESTAMP_SOURCE_FIELDS = ["checkedAt", "expiresAt"];
47
+ const EXPIRY_UNAVAILABLE_SOURCE_FIELDS = ["checkedAt", "expiryStatus"];
48
+ const RAW_AMOUNT_SOURCE_FIELDS = ["rawAmount", "asset", "amountRole"];
49
+ const MIN_OUT_AMOUNT_SOURCE_FIELDS = ["minOutRaw", "asset", "amountRole"];
50
+ const GAS_BUDGET_AMOUNT_SOURCE_FIELDS = ["gasBudgetRaw", "asset", "amountRole"];
51
+ const GAS_USED_AMOUNT_SOURCE_FIELDS = ["gasUsedRaw", "asset", "amountRole"];
52
+ const GAS_UNRESOLVED_SOURCE_FIELDS = ["checkedAt", "gasResolutionStatus", "unresolvedReason"];
53
+ const BALANCE_DELTA_AMOUNT_SOURCE_FIELDS = ["balanceChanges", "asset", "amountRole"];
54
+ const UNIT_SOURCE_FIELDS = ["coinType", "decimals"];
55
+ const QUOTE_MIN_OUT_SOURCE_FIELDS = ["quoteEvidenceId", "minOutRaw"];
56
+ const USER_SLIPPAGE_POLICY_SOURCE_FIELDS = ["maxSlippageBps", "userSelection"];
57
+ const ADAPTER_SLIPPAGE_POLICY_SOURCE_FIELDS = ["maxSlippageBps", "minOutRaw"];
58
+ const OBJECT_OWNERSHIP_SOURCE_FIELDS = ["ownerAccount", "objects"];
59
+ const ADAPTER_SOURCE_OF_TRUTH_KINDS = [
60
+ "pinned_sdk_registry",
61
+ "verified_mainnet_onchain_metadata",
62
+ "wallet_account_read",
63
+ "quote_evidence",
64
+ "review_time_simulation",
65
+ "validated_request_fact",
66
+ "user_explicit_choice"
67
+ ];
68
+ const RAW_QUANTITY_ROLES = [
69
+ "input",
70
+ "expected_output",
71
+ "minimum_output",
72
+ "gas_budget",
73
+ "gas_used",
74
+ "fee",
75
+ "balance_delta"
76
+ ];
77
+ const SAFETY_CRITICAL_FACT_KINDS = [
78
+ "raw_quantity_amount",
79
+ "unit_metadata",
80
+ "gas_unresolved_status",
81
+ "expiry_status",
82
+ "quote_min_out",
83
+ "slippage_policy",
84
+ "object_ownership",
85
+ "simulation_result"
86
+ ];
87
+ const RAW_QUANTITY_AMOUNT_EVIDENCE_BY_ROLE = {
88
+ input: {
89
+ kinds: ["validated_request_fact", "wallet_account_read", "user_explicit_choice"],
90
+ fields: RAW_AMOUNT_SOURCE_FIELDS
91
+ },
92
+ expected_output: {
93
+ kinds: ["quote_evidence", "review_time_simulation"],
94
+ fields: RAW_AMOUNT_SOURCE_FIELDS
95
+ },
96
+ minimum_output: {
97
+ kinds: ["quote_evidence"],
98
+ fields: MIN_OUT_AMOUNT_SOURCE_FIELDS
99
+ },
100
+ gas_budget: {
101
+ kinds: ["review_time_simulation"],
102
+ fields: GAS_BUDGET_AMOUNT_SOURCE_FIELDS
103
+ },
104
+ gas_used: {
105
+ kinds: ["review_time_simulation"],
106
+ fields: GAS_USED_AMOUNT_SOURCE_FIELDS
107
+ },
108
+ fee: {
109
+ kinds: ["review_time_simulation"],
110
+ fields: RAW_AMOUNT_SOURCE_FIELDS
111
+ },
112
+ balance_delta: {
113
+ kinds: ["review_time_simulation"],
114
+ fields: BALANCE_DELTA_AMOUNT_SOURCE_FIELDS
115
+ }
116
+ };
117
+ const UNIT_EVIDENCE_BY_SOURCE = {
118
+ pinned_sdk_metadata: {
119
+ kinds: ["pinned_sdk_registry"],
120
+ fields: UNIT_SOURCE_FIELDS
121
+ },
122
+ verified_mainnet_onchain_metadata: {
123
+ kinds: ["verified_mainnet_onchain_metadata"],
124
+ fields: UNIT_SOURCE_FIELDS
125
+ }
126
+ };
127
+ const SLIPPAGE_POLICY_EVIDENCE_BY_SOURCE = {
128
+ user_explicit: {
129
+ kinds: ["user_explicit_choice"],
130
+ fields: USER_SLIPPAGE_POLICY_SOURCE_FIELDS
131
+ },
132
+ adapter_policy_from_quote_evidence: {
133
+ kinds: ["quote_evidence"],
134
+ fields: ADAPTER_SLIPPAGE_POLICY_SOURCE_FIELDS
135
+ }
136
+ };
137
+ const GAS_UNRESOLVED_EVIDENCE_REQUIREMENT = {
138
+ kinds: ["review_time_simulation"],
139
+ fields: GAS_UNRESOLVED_SOURCE_FIELDS
140
+ };
141
+ const QUOTE_MIN_OUT_EVIDENCE_REQUIREMENT = {
142
+ kinds: ["quote_evidence"],
143
+ fields: QUOTE_MIN_OUT_SOURCE_FIELDS
144
+ };
145
+ const EXPIRY_EVIDENCE_REQUIREMENT = {
146
+ kinds: ["validated_request_fact"],
147
+ fields: EXPIRY_TIMESTAMP_SOURCE_FIELDS
148
+ };
149
+ const EXPIRY_UNAVAILABLE_EVIDENCE_REQUIREMENT = {
150
+ kinds: ["validated_request_fact"],
151
+ fields: EXPIRY_UNAVAILABLE_SOURCE_FIELDS
152
+ };
153
+ const OBJECT_OWNERSHIP_EVIDENCE_REQUIREMENT = {
154
+ kinds: ["wallet_account_read"],
155
+ fields: OBJECT_OWNERSHIP_SOURCE_FIELDS
156
+ };
157
+ const SIMULATION_RESULT_EVIDENCE_REQUIREMENT = {
158
+ kinds: ["review_time_simulation"],
159
+ fields: WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS
160
+ };
161
+ export const SAFETY_CRITICAL_FACT_MATRIX = {
162
+ raw_quantity_amount: {
163
+ byRole: RAW_QUANTITY_AMOUNT_EVIDENCE_BY_ROLE
164
+ },
165
+ unit_metadata: {
166
+ bySource: UNIT_EVIDENCE_BY_SOURCE
167
+ },
168
+ gas_unresolved_status: GAS_UNRESOLVED_EVIDENCE_REQUIREMENT,
169
+ expiry_status: {
170
+ current: EXPIRY_EVIDENCE_REQUIREMENT,
171
+ expired: EXPIRY_EVIDENCE_REQUIREMENT,
172
+ not_provided: EXPIRY_UNAVAILABLE_EVIDENCE_REQUIREMENT,
173
+ not_applicable: EXPIRY_UNAVAILABLE_EVIDENCE_REQUIREMENT
174
+ },
175
+ quote_min_out: QUOTE_MIN_OUT_EVIDENCE_REQUIREMENT,
176
+ slippage_policy: {
177
+ bySource: SLIPPAGE_POLICY_EVIDENCE_BY_SOURCE
178
+ },
179
+ object_ownership: OBJECT_OWNERSHIP_EVIDENCE_REQUIREMENT,
180
+ simulation_result: SIMULATION_RESULT_EVIDENCE_REQUIREMENT
181
+ };
182
+ export const CONSUMER_INVARIANT_MATRIX = {
183
+ gasBudgetClaimId: {
184
+ factKind: "raw_quantity_amount",
185
+ role: "gas_budget",
186
+ assetCoinType: SUI_GAS_COIN_TYPE,
187
+ rawUnit: SUI_GAS_RAW_UNIT
188
+ },
189
+ gasUsedClaimId: {
190
+ factKind: "raw_quantity_amount",
191
+ role: "gas_used",
192
+ assetCoinType: SUI_GAS_COIN_TYPE,
193
+ rawUnit: SUI_GAS_RAW_UNIT
194
+ },
195
+ gasObjectOwnershipClaimId: {
196
+ factKind: "object_ownership",
197
+ ownership: "owned_by_account"
198
+ }
199
+ };
200
+ const isoUtcStringSchema = z.string().refine((value) => {
201
+ const parsed = new Date(value);
202
+ return !Number.isNaN(parsed.getTime()) && parsed.toISOString() === value;
203
+ }, "Expected ISO 8601 UTC timestamp");
204
+ const unsignedIntegerStringSchema = makeCanonicalRawU64StringSchema("unsigned integer");
205
+ const suiObjectIdSchema = z.string().regex(/^0x[0-9a-fA-F]{1,64}$/, {
206
+ message: "Expected a Sui object id"
207
+ });
208
+ const coinTypeSchema = z.string().min(1).max(512).refine((value) => {
209
+ try {
210
+ return normalizeCoinType(value) === value;
211
+ }
212
+ catch {
213
+ return false;
214
+ }
215
+ }, "Expected a normalized Sui struct tag coin type");
216
+ const evidenceIdSchema = z.string().min(1).max(120);
217
+ const resolvedAssetReferenceSchema = z.object({
218
+ symbol: z.string().min(1).max(64).optional(),
219
+ coinType: coinTypeSchema
220
+ }).strict();
221
+ const EXECUTABLE_MATERIAL_TEXT_PATTERN = /transaction\s*bytes?|tx\s*bytes?|serialized\s*transaction|serializedTransaction|signed\s*transaction|signing\s*request|signingRequest|wallet\s*authorization|walletAuthorization|private\s*key|privateKey|secret\s*key|secretKey|seed\s*phrase|mnemonic|suiprivkey|signature|bcs\s*transaction/i;
222
+ const LONG_HEX_OR_BASE64LIKE_PAYLOAD_PATTERN = /(?:0x[0-9a-fA-F]{160,}|[A-Za-z0-9+/_=-]{160,})/;
223
+ function displayTextWithoutExecutableMaterial(maxLength, fieldName) {
224
+ return z.string().min(1).max(maxLength).superRefine((value, ctx) => {
225
+ if (EXECUTABLE_MATERIAL_TEXT_PATTERN.test(value) ||
226
+ LONG_HEX_OR_BASE64LIKE_PAYLOAD_PATTERN.test(value)) {
227
+ ctx.addIssue({
228
+ code: z.ZodIssueCode.custom,
229
+ message: `${fieldName} must not contain executable transaction, signing, private-key, mnemonic, or long encoded material`
230
+ });
231
+ }
232
+ });
233
+ }
234
+ function missingRequiredValues(values, required) {
235
+ const present = new Set(values);
236
+ return required.filter((value) => !present.has(value));
237
+ }
238
+ function addMissingRequiredValuesIssue(ctx, values, required, path, label) {
239
+ const missing = missingRequiredValues(values, required);
240
+ if (missing.length === 0) {
241
+ return;
242
+ }
243
+ ctx.addIssue({
244
+ code: z.ZodIssueCode.custom,
245
+ path,
246
+ message: `${label} must include ${missing.join(", ")}`
247
+ });
248
+ }
249
+ function requireAllValues(ctx, values, required, path, label) {
250
+ addMissingRequiredValuesIssue(ctx, values, required, path, label);
251
+ }
252
+ function addMismatchIssue(ctx, path, label) {
253
+ ctx.addIssue({
254
+ code: z.ZodIssueCode.custom,
255
+ path,
256
+ message: `${label} must match referenced evidence claim`
257
+ });
258
+ }
259
+ function requireEqual(ctx, actual, expected, path, label) {
260
+ if (actual !== expected) {
261
+ addMismatchIssue(ctx, path, label);
262
+ }
263
+ }
264
+ function requireSameStringSet(ctx, actual, expected, path, label) {
265
+ const actualSet = new Set(actual);
266
+ const expectedSet = new Set(expected);
267
+ if (actualSet.size !== expectedSet.size) {
268
+ addMismatchIssue(ctx, path, label);
269
+ return;
270
+ }
271
+ for (const value of actualSet) {
272
+ if (!expectedSet.has(value)) {
273
+ addMismatchIssue(ctx, path, label);
274
+ return;
275
+ }
276
+ }
277
+ }
278
+ function requireSameAsset(ctx, actual, expected, path, label) {
279
+ if (actual.symbol !== expected.symbol || actual.coinType !== expected.coinType) {
280
+ addMismatchIssue(ctx, path, label);
281
+ }
282
+ }
283
+ function requireGasAsset(ctx, asset, expectedCoinType, path, label) {
284
+ try {
285
+ if (normalizeCoinType(asset.coinType) !== expectedCoinType) {
286
+ addMismatchIssue(ctx, path, label);
287
+ }
288
+ }
289
+ catch {
290
+ addMismatchIssue(ctx, path, label);
291
+ }
292
+ }
293
+ export const adapterInputProvenanceSchema = z.object({
294
+ kind: z.enum(["natural_language_intent", "external_proposal", "mcp_action_request", "local_review_request"]),
295
+ sourceId: z.string().min(1).max(160),
296
+ capturedAt: isoUtcStringSchema,
297
+ authority: z.literal("untrusted_until_review_regenerates_and_verifies"),
298
+ userSelectionSource: z.enum(["user_explicit", "prior_user_explicit_context"]).optional()
299
+ }).strict();
300
+ export const adapterSourceOfTruthSchema = z.object({
301
+ id: evidenceIdSchema,
302
+ kind: z.enum(ADAPTER_SOURCE_OF_TRUTH_KINDS),
303
+ network: z.literal("sui:mainnet"),
304
+ source: z.string().min(1).max(240),
305
+ verifiedAt: isoUtcStringSchema,
306
+ fields: z.array(z.string().min(1).max(120)).min(1)
307
+ }).strict();
308
+ const rawQuantityAmountClaimSchema = z.object({
309
+ id: evidenceIdSchema,
310
+ factKind: z.literal("raw_quantity_amount"),
311
+ sourceEvidenceId: evidenceIdSchema,
312
+ role: z.enum(RAW_QUANTITY_ROLES),
313
+ asset: resolvedAssetReferenceSchema,
314
+ rawAmount: unsignedIntegerStringSchema
315
+ }).strict();
316
+ const unitMetadataClaimSchema = z.object({
317
+ id: evidenceIdSchema,
318
+ factKind: z.literal("unit_metadata"),
319
+ sourceEvidenceId: evidenceIdSchema,
320
+ source: z.enum(["pinned_sdk_metadata", "verified_mainnet_onchain_metadata"]),
321
+ coinType: coinTypeSchema,
322
+ decimals: z.number().int().min(0).max(255)
323
+ }).strict();
324
+ const gasUnresolvedStatusClaimSchema = z.object({
325
+ id: evidenceIdSchema,
326
+ factKind: z.literal("gas_unresolved_status"),
327
+ sourceEvidenceId: evidenceIdSchema,
328
+ checkedAt: isoUtcStringSchema,
329
+ status: z.literal("unresolved"),
330
+ reason: z.string().min(1).max(240)
331
+ }).strict();
332
+ const expiryStatusClaimSchema = z.object({
333
+ id: evidenceIdSchema,
334
+ factKind: z.literal("expiry_status"),
335
+ sourceEvidenceId: evidenceIdSchema,
336
+ checkedAt: isoUtcStringSchema,
337
+ status: z.enum(["current", "expired", "not_provided", "not_applicable"]),
338
+ expiresAt: isoUtcStringSchema.optional(),
339
+ reason: z.string().min(1).max(240).optional()
340
+ }).strict();
341
+ const quoteMinOutClaimSchema = z.object({
342
+ id: evidenceIdSchema,
343
+ factKind: z.literal("quote_min_out"),
344
+ sourceEvidenceId: evidenceIdSchema,
345
+ quoteEvidenceId: z.string().min(1).max(120),
346
+ minOutRaw: unsignedIntegerStringSchema
347
+ }).strict();
348
+ const slippagePolicyClaimSchema = z.object({
349
+ id: evidenceIdSchema,
350
+ factKind: z.literal("slippage_policy"),
351
+ sourceEvidenceId: evidenceIdSchema,
352
+ policySource: z.enum(["user_explicit", "adapter_policy_from_quote_evidence"]),
353
+ maxSlippageBps: z.number().int().min(0).max(10_000),
354
+ minOutRaw: unsignedIntegerStringSchema.optional()
355
+ }).strict();
356
+ const objectOwnershipClaimSchema = z.object({
357
+ id: evidenceIdSchema,
358
+ factKind: z.literal("object_ownership"),
359
+ sourceEvidenceId: evidenceIdSchema,
360
+ objectId: suiObjectIdSchema,
361
+ ownerAccount: suiAddressStringSchema,
362
+ ownership: z.enum(["owned_by_account", "shared_object", "immutable_or_package", "not_owned_by_account"])
363
+ }).strict();
364
+ const simulationResultClaimSchema = z.object({
365
+ id: evidenceIdSchema,
366
+ factKind: z.literal("simulation_result"),
367
+ sourceEvidenceId: evidenceIdSchema,
368
+ provider: z.literal("client.core.simulateTransaction"),
369
+ checksEnabled: z.literal(true),
370
+ simulatedAt: isoUtcStringSchema,
371
+ status: z.enum(["success", "failed", "unavailable"]),
372
+ requiredFields: z.array(z.enum(WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS)).min(WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS.length),
373
+ missingFields: z.array(z.enum(WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS)).default([]),
374
+ failureReason: z.string().min(1).max(240).optional()
375
+ }).strict();
376
+ export const adapterEvidenceClaimSchema = z.discriminatedUnion("factKind", [
377
+ rawQuantityAmountClaimSchema,
378
+ unitMetadataClaimSchema,
379
+ gasUnresolvedStatusClaimSchema,
380
+ expiryStatusClaimSchema,
381
+ quoteMinOutClaimSchema,
382
+ slippagePolicyClaimSchema,
383
+ objectOwnershipClaimSchema,
384
+ simulationResultClaimSchema
385
+ ]);
386
+ export const adapterRawQuantitySchema = z.object({
387
+ id: evidenceIdSchema,
388
+ role: z.enum(RAW_QUANTITY_ROLES),
389
+ asset: resolvedAssetReferenceSchema,
390
+ rawAmount: unsignedIntegerStringSchema,
391
+ unit: z.object({
392
+ decimals: z.number().int().min(0).max(255),
393
+ source: z.enum(["pinned_sdk_metadata", "verified_mainnet_onchain_metadata"]),
394
+ sourceField: z.string().min(1).max(160),
395
+ unitClaimId: evidenceIdSchema
396
+ }).strict(),
397
+ amountClaimId: evidenceIdSchema,
398
+ displayOnly: z.object({
399
+ amountDisplay: z.string().min(1).max(120),
400
+ reason: z.literal("presentation_only_not_signing_input")
401
+ }).strict().optional()
402
+ }).strict();
403
+ export const adapterGasObjectOwnershipLinkSchema = z.object({
404
+ objectId: suiObjectIdSchema,
405
+ ownerAccount: suiAddressStringSchema,
406
+ ownershipClaimId: evidenceIdSchema
407
+ }).strict();
408
+ export const adapterGasEvidenceSchema = z.object({
409
+ source: z.literal("review_time_simulation"),
410
+ checkedAt: isoUtcStringSchema,
411
+ gasBudgetRaw: unsignedIntegerStringSchema.optional(),
412
+ gasBudgetClaimId: evidenceIdSchema.optional(),
413
+ gasUsedRaw: unsignedIntegerStringSchema.optional(),
414
+ gasUsedClaimId: evidenceIdSchema.optional(),
415
+ gasObjects: z.array(adapterGasObjectOwnershipLinkSchema).optional(),
416
+ unresolvedReason: z.string().min(1).max(240).optional(),
417
+ unresolvedClaimId: evidenceIdSchema.optional()
418
+ }).strict().superRefine((value, ctx) => {
419
+ const hasRawGas = value.gasBudgetRaw !== undefined || value.gasUsedRaw !== undefined;
420
+ if (!hasRawGas && value.unresolvedReason === undefined) {
421
+ ctx.addIssue({
422
+ code: z.ZodIssueCode.custom,
423
+ message: "Expected gas evidence or unresolvedReason"
424
+ });
425
+ }
426
+ if (hasRawGas && value.unresolvedReason !== undefined) {
427
+ ctx.addIssue({
428
+ code: z.ZodIssueCode.custom,
429
+ path: ["unresolvedReason"],
430
+ message: "Resolved gas quantities must not include unresolvedReason"
431
+ });
432
+ }
433
+ if (value.gasBudgetRaw !== undefined && value.gasBudgetClaimId === undefined) {
434
+ ctx.addIssue({
435
+ code: z.ZodIssueCode.custom,
436
+ path: ["gasBudgetClaimId"],
437
+ message: "gasBudgetRaw requires gasBudgetClaimId"
438
+ });
439
+ }
440
+ if (value.gasBudgetRaw === undefined && value.gasBudgetClaimId !== undefined) {
441
+ ctx.addIssue({
442
+ code: z.ZodIssueCode.custom,
443
+ path: ["gasBudgetClaimId"],
444
+ message: "gasBudgetClaimId requires gasBudgetRaw"
445
+ });
446
+ }
447
+ if (value.gasUsedRaw !== undefined && value.gasUsedClaimId === undefined) {
448
+ ctx.addIssue({
449
+ code: z.ZodIssueCode.custom,
450
+ path: ["gasUsedClaimId"],
451
+ message: "gasUsedRaw requires gasUsedClaimId"
452
+ });
453
+ }
454
+ if (value.gasUsedRaw === undefined && value.gasUsedClaimId !== undefined) {
455
+ ctx.addIssue({
456
+ code: z.ZodIssueCode.custom,
457
+ path: ["gasUsedClaimId"],
458
+ message: "gasUsedClaimId requires gasUsedRaw"
459
+ });
460
+ }
461
+ if (value.unresolvedReason !== undefined && value.unresolvedClaimId === undefined) {
462
+ ctx.addIssue({
463
+ code: z.ZodIssueCode.custom,
464
+ path: ["unresolvedClaimId"],
465
+ message: "unresolvedReason requires unresolvedClaimId"
466
+ });
467
+ }
468
+ if (value.unresolvedReason === undefined && value.unresolvedClaimId !== undefined) {
469
+ ctx.addIssue({
470
+ code: z.ZodIssueCode.custom,
471
+ path: ["unresolvedClaimId"],
472
+ message: "unresolvedClaimId requires unresolvedReason"
473
+ });
474
+ }
475
+ });
476
+ export const adapterExpiryEvidenceSchema = z.discriminatedUnion("status", [
477
+ z.object({
478
+ checkedAt: isoUtcStringSchema,
479
+ status: z.literal("current"),
480
+ expiresAt: isoUtcStringSchema,
481
+ evidenceClaimId: evidenceIdSchema
482
+ }).strict(),
483
+ z.object({
484
+ checkedAt: isoUtcStringSchema,
485
+ status: z.literal("expired"),
486
+ expiresAt: isoUtcStringSchema,
487
+ evidenceClaimId: evidenceIdSchema
488
+ }).strict(),
489
+ z.object({
490
+ checkedAt: isoUtcStringSchema,
491
+ status: z.literal("not_provided"),
492
+ evidenceClaimId: evidenceIdSchema,
493
+ reason: z.string().min(1).max(240),
494
+ expiresAt: z.never().optional()
495
+ }).strict(),
496
+ z.object({
497
+ checkedAt: isoUtcStringSchema,
498
+ status: z.literal("not_applicable"),
499
+ evidenceClaimId: evidenceIdSchema,
500
+ reason: z.string().min(1).max(240),
501
+ expiresAt: z.never().optional()
502
+ }).strict()
503
+ ]).superRefine((value, ctx) => {
504
+ if (value.status === "current" && Date.parse(value.expiresAt) <= Date.parse(value.checkedAt)) {
505
+ ctx.addIssue({
506
+ code: z.ZodIssueCode.custom,
507
+ path: ["expiresAt"],
508
+ message: "Current expiry evidence requires expiresAt after checkedAt"
509
+ });
510
+ }
511
+ if (value.status === "expired" && Date.parse(value.expiresAt) > Date.parse(value.checkedAt)) {
512
+ ctx.addIssue({
513
+ code: z.ZodIssueCode.custom,
514
+ path: ["expiresAt"],
515
+ message: "Expired expiry evidence requires expiresAt at or before checkedAt"
516
+ });
517
+ }
518
+ });
519
+ export const adapterSlippageOrMinOutEvidenceSchema = z.object({
520
+ status: z.enum(["required_and_verified", "not_required_for_action", "missing", "stale"]),
521
+ quoteEvidenceId: z.string().min(1).max(120).optional(),
522
+ quoteEvidenceClaimId: evidenceIdSchema.optional(),
523
+ maxSlippageBps: z.number().int().min(0).max(10_000).optional(),
524
+ minOutRaw: unsignedIntegerStringSchema.optional(),
525
+ policySource: z.enum(["user_explicit", "adapter_policy_from_quote_evidence"]).optional(),
526
+ policyEvidenceClaimId: evidenceIdSchema.optional()
527
+ }).strict().superRefine((value, ctx) => {
528
+ if (value.status === "required_and_verified" &&
529
+ (value.quoteEvidenceId === undefined ||
530
+ value.quoteEvidenceClaimId === undefined ||
531
+ value.maxSlippageBps === undefined ||
532
+ value.minOutRaw === undefined ||
533
+ value.policySource === undefined ||
534
+ value.policyEvidenceClaimId === undefined)) {
535
+ ctx.addIssue({
536
+ code: z.ZodIssueCode.custom,
537
+ message: "Verified min-out evidence requires quoteEvidenceId, quoteEvidenceClaimId, maxSlippageBps, minOutRaw, policySource, and policyEvidenceClaimId"
538
+ });
539
+ }
540
+ if (value.quoteEvidenceId !== undefined && value.quoteEvidenceClaimId === undefined) {
541
+ ctx.addIssue({
542
+ code: z.ZodIssueCode.custom,
543
+ path: ["quoteEvidenceClaimId"],
544
+ message: "quoteEvidenceId requires quoteEvidenceClaimId"
545
+ });
546
+ }
547
+ if (value.quoteEvidenceId === undefined && value.quoteEvidenceClaimId !== undefined) {
548
+ ctx.addIssue({
549
+ code: z.ZodIssueCode.custom,
550
+ path: ["quoteEvidenceClaimId"],
551
+ message: "quoteEvidenceClaimId requires quoteEvidenceId"
552
+ });
553
+ }
554
+ if (value.minOutRaw !== undefined && value.quoteEvidenceClaimId === undefined) {
555
+ ctx.addIssue({
556
+ code: z.ZodIssueCode.custom,
557
+ path: ["quoteEvidenceClaimId"],
558
+ message: "minOutRaw requires quoteEvidenceClaimId"
559
+ });
560
+ }
561
+ if (value.maxSlippageBps !== undefined && value.policySource === undefined) {
562
+ ctx.addIssue({
563
+ code: z.ZodIssueCode.custom,
564
+ path: ["policySource"],
565
+ message: "maxSlippageBps requires policySource"
566
+ });
567
+ }
568
+ if (value.policySource !== undefined && value.policyEvidenceClaimId === undefined) {
569
+ ctx.addIssue({
570
+ code: z.ZodIssueCode.custom,
571
+ path: ["policyEvidenceClaimId"],
572
+ message: "policySource requires policyEvidenceClaimId"
573
+ });
574
+ }
575
+ if (value.policySource === undefined && value.policyEvidenceClaimId !== undefined) {
576
+ ctx.addIssue({
577
+ code: z.ZodIssueCode.custom,
578
+ path: ["policyEvidenceClaimId"],
579
+ message: "policyEvidenceClaimId requires policySource"
580
+ });
581
+ }
582
+ });
583
+ export const adapterObjectOwnershipEvidenceSchema = z.object({
584
+ checkedAt: isoUtcStringSchema,
585
+ ownerAccount: suiAddressStringSchema,
586
+ objects: z.array(z.object({
587
+ objectId: suiObjectIdSchema,
588
+ role: z.enum(["input_coin", "gas_coin", "protocol_object", "shared_object", "receiving_object"]),
589
+ ownership: z.enum(["owned_by_account", "shared_object", "immutable_or_package", "not_owned_by_account"]),
590
+ evidenceClaimId: evidenceIdSchema
591
+ }).strict()).min(1)
592
+ }).strict();
593
+ export const adapterSimulationEvidenceSchema = z.object({
594
+ evidenceClaimId: evidenceIdSchema,
595
+ boundToCommitment: suiTransactionDigestSchema,
596
+ provider: z.literal("client.core.simulateTransaction"),
597
+ checksEnabled: z.literal(true),
598
+ simulatedAt: isoUtcStringSchema,
599
+ status: z.enum(["success", "failed", "unavailable"]),
600
+ requiredFields: z.array(z.enum(WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS)).min(WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS.length),
601
+ missingFields: z.array(z.enum(WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS)).default([]),
602
+ failureReason: z.string().min(1).max(240).optional()
603
+ }).strict().refine((value) => value.status !== "success" || value.missingFields.length === 0, {
604
+ message: "Successful simulation evidence must not have missing required fields"
605
+ }).refine((value) => WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS.every((field) => value.requiredFields.includes(field)), {
606
+ message: "Simulation evidence must include every required simulation field"
607
+ }).refine((value) => value.status === "success" || value.failureReason !== undefined, {
608
+ message: "Failed or unavailable simulation evidence requires failureReason"
609
+ }).refine((value) => value.status !== "success" || value.failureReason === undefined, {
610
+ message: "Successful simulation evidence must not include failureReason"
611
+ });
612
+ export const adapterHumanReadableReviewSchema = z.object({
613
+ fields: z.array(z.enum(WALLET_REVIEW_REQUIRED_HUMAN_FIELDS)).min(WALLET_REVIEW_REQUIRED_HUMAN_FIELDS.length),
614
+ boundToCommitment: suiTransactionDigestSchema,
615
+ source: z.literal("review_model_or_adapter_equivalent"),
616
+ purpose: z.literal("human_review_before_wallet_authorization")
617
+ }).strict().refine((value) => WALLET_REVIEW_REQUIRED_HUMAN_FIELDS.every((field) => value.fields.includes(field)), {
618
+ message: "Human-readable review fields must include every required review field"
619
+ });
620
+ export const adapterOutputBoundarySchema = z.object({
621
+ runtimeStatus: z.literal("emitted_pre_handoff"),
622
+ mcpAndReviewUiMayExpose: z.array(z.enum([
623
+ "human_readable_review",
624
+ "ptb_visualization_artifact",
625
+ "diagnostics",
626
+ "status_checks"
627
+ ])).min(1),
628
+ prohibited: z.array(z.enum(WALLET_REVIEW_REQUIRED_PROHIBITED_OUTPUTS)).min(1)
629
+ }).strict().superRefine((value, ctx) => {
630
+ requireAllValues(ctx, value.prohibited, WALLET_REVIEW_REQUIRED_PROHIBITED_OUTPUTS, ["prohibited"], "prohibited");
631
+ });
632
+ export const walletReviewAdapterContractSchema = z.object({
633
+ contractVersion: z.literal(WALLET_REVIEW_ADAPTER_CONTRACT_VERSION),
634
+ adapterId: z.string().min(1).max(120),
635
+ protocol: z.string().min(1).max(120),
636
+ actionKind: z.string().min(1).max(120),
637
+ network: z.literal("sui:mainnet"),
638
+ inputProvenance: adapterInputProvenanceSchema,
639
+ sourceOfTruth: z.array(adapterSourceOfTruthSchema).min(1),
640
+ evidenceClaims: z.array(adapterEvidenceClaimSchema).min(1),
641
+ rawQuantities: z.array(adapterRawQuantitySchema).min(1),
642
+ gas: adapterGasEvidenceSchema,
643
+ expiry: adapterExpiryEvidenceSchema,
644
+ slippageOrMinOut: adapterSlippageOrMinOutEvidenceSchema,
645
+ objectOwnership: adapterObjectOwnershipEvidenceSchema,
646
+ simulation: adapterSimulationEvidenceSchema,
647
+ humanReadableReview: adapterHumanReadableReviewSchema,
648
+ outputBoundary: adapterOutputBoundarySchema,
649
+ transactionMaterialCommitment: suiTransactionDigestSchema
650
+ }).strict().superRefine((value, ctx) => {
651
+ const sourceIds = new Set();
652
+ const sourceById = new Map();
653
+ const sourceIndexById = new Map();
654
+ value.sourceOfTruth.forEach((source, index) => {
655
+ if (sourceIds.has(source.id)) {
656
+ ctx.addIssue({
657
+ code: z.ZodIssueCode.custom,
658
+ path: ["sourceOfTruth", index, "id"],
659
+ message: `sourceOfTruth id must be unique: ${source.id}`
660
+ });
661
+ }
662
+ sourceIds.add(source.id);
663
+ if (!sourceById.has(source.id)) {
664
+ sourceById.set(source.id, source);
665
+ sourceIndexById.set(source.id, index);
666
+ }
667
+ });
668
+ const claimIds = new Set();
669
+ const claimById = new Map();
670
+ const claimIndexById = new Map();
671
+ value.evidenceClaims.forEach((claim, index) => {
672
+ if (claimIds.has(claim.id)) {
673
+ ctx.addIssue({
674
+ code: z.ZodIssueCode.custom,
675
+ path: ["evidenceClaims", index, "id"],
676
+ message: `evidenceClaims id must be unique: ${claim.id}`
677
+ });
678
+ }
679
+ claimIds.add(claim.id);
680
+ if (!claimById.has(claim.id)) {
681
+ claimById.set(claim.id, claim);
682
+ claimIndexById.set(claim.id, index);
683
+ }
684
+ });
685
+ const requireSourceId = (sourceEvidenceId, path) => {
686
+ if (sourceEvidenceId === undefined) {
687
+ return undefined;
688
+ }
689
+ const source = sourceById.get(sourceEvidenceId);
690
+ if (source !== undefined) {
691
+ return source;
692
+ }
693
+ ctx.addIssue({
694
+ code: z.ZodIssueCode.custom,
695
+ path,
696
+ message: `source evidence id must reference sourceOfTruth[].id: ${sourceEvidenceId}`
697
+ });
698
+ return undefined;
699
+ };
700
+ const requireSourceEvidence = (sourceEvidenceId, requirement, path, label) => {
701
+ if (sourceEvidenceId === undefined) {
702
+ return;
703
+ }
704
+ const source = requireSourceId(sourceEvidenceId, path);
705
+ if (source === undefined) {
706
+ return;
707
+ }
708
+ const sourceIndex = sourceIndexById.get(sourceEvidenceId);
709
+ const sourcePath = sourceIndex === undefined ? path : ["sourceOfTruth", sourceIndex];
710
+ if (!requirement.kinds.includes(source.kind)) {
711
+ ctx.addIssue({
712
+ code: z.ZodIssueCode.custom,
713
+ path: [...sourcePath, "kind"],
714
+ message: `${label} source kind must be one of ${requirement.kinds.join(", ")}`
715
+ });
716
+ }
717
+ addMissingRequiredValuesIssue(ctx, source.fields, requirement.fields, [...sourcePath, "fields"], `${label} sourceOfTruth fields`);
718
+ };
719
+ const requireClaim = (claimId, factKind, path, label) => {
720
+ if (claimId === undefined) {
721
+ ctx.addIssue({
722
+ code: z.ZodIssueCode.custom,
723
+ path,
724
+ message: `${label} must reference evidenceClaims[].id`
725
+ });
726
+ return undefined;
727
+ }
728
+ const claim = claimById.get(claimId);
729
+ if (claim === undefined) {
730
+ ctx.addIssue({
731
+ code: z.ZodIssueCode.custom,
732
+ path,
733
+ message: `${label} must reference evidenceClaims[].id: ${claimId}`
734
+ });
735
+ return undefined;
736
+ }
737
+ if (claim.factKind !== factKind) {
738
+ const claimIndex = claimIndexById.get(claimId);
739
+ const claimPath = claimIndex === undefined ? path : ["evidenceClaims", claimIndex, "factKind"];
740
+ ctx.addIssue({
741
+ code: z.ZodIssueCode.custom,
742
+ path: claimPath,
743
+ message: `${label} evidence claim factKind must be ${factKind}`
744
+ });
745
+ }
746
+ return claim;
747
+ };
748
+ value.evidenceClaims.forEach((claim, index) => {
749
+ if (claim.factKind === "raw_quantity_amount") {
750
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.raw_quantity_amount.byRole[claim.role], ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].raw_quantity_amount`);
751
+ }
752
+ if (claim.factKind === "unit_metadata") {
753
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.unit_metadata.bySource[claim.source], ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].unit_metadata`);
754
+ }
755
+ if (claim.factKind === "gas_unresolved_status") {
756
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.gas_unresolved_status, ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].gas_unresolved_status`);
757
+ }
758
+ if (claim.factKind === "expiry_status") {
759
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.expiry_status[claim.status], ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].expiry_status`);
760
+ if ((claim.status === "current" || claim.status === "expired") && claim.expiresAt === undefined) {
761
+ ctx.addIssue({
762
+ code: z.ZodIssueCode.custom,
763
+ path: ["evidenceClaims", index, "expiresAt"],
764
+ message: "Current or expired expiry claim requires expiresAt"
765
+ });
766
+ }
767
+ if ((claim.status === "not_provided" || claim.status === "not_applicable") && claim.reason === undefined) {
768
+ ctx.addIssue({
769
+ code: z.ZodIssueCode.custom,
770
+ path: ["evidenceClaims", index, "reason"],
771
+ message: "Unavailable expiry claim requires reason"
772
+ });
773
+ }
774
+ if ((claim.status === "not_provided" || claim.status === "not_applicable") && claim.expiresAt !== undefined) {
775
+ ctx.addIssue({
776
+ code: z.ZodIssueCode.custom,
777
+ path: ["evidenceClaims", index, "expiresAt"],
778
+ message: "Unavailable expiry claim must not include expiresAt"
779
+ });
780
+ }
781
+ if (claim.status === "current" &&
782
+ claim.expiresAt !== undefined &&
783
+ Date.parse(claim.expiresAt) <= Date.parse(claim.checkedAt)) {
784
+ ctx.addIssue({
785
+ code: z.ZodIssueCode.custom,
786
+ path: ["evidenceClaims", index, "expiresAt"],
787
+ message: "Current expiry claim requires expiresAt after checkedAt"
788
+ });
789
+ }
790
+ if (claim.status === "expired" &&
791
+ claim.expiresAt !== undefined &&
792
+ Date.parse(claim.expiresAt) > Date.parse(claim.checkedAt)) {
793
+ ctx.addIssue({
794
+ code: z.ZodIssueCode.custom,
795
+ path: ["evidenceClaims", index, "expiresAt"],
796
+ message: "Expired expiry claim requires expiresAt at or before checkedAt"
797
+ });
798
+ }
799
+ }
800
+ if (claim.factKind === "quote_min_out") {
801
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.quote_min_out, ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].quote_min_out`);
802
+ }
803
+ if (claim.factKind === "slippage_policy") {
804
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.slippage_policy.bySource[claim.policySource], ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].slippage_policy`);
805
+ if (claim.policySource === "adapter_policy_from_quote_evidence" && claim.minOutRaw === undefined) {
806
+ ctx.addIssue({
807
+ code: z.ZodIssueCode.custom,
808
+ path: ["evidenceClaims", index, "minOutRaw"],
809
+ message: "Adapter-derived slippage policy claim requires minOutRaw"
810
+ });
811
+ }
812
+ }
813
+ if (claim.factKind === "object_ownership") {
814
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.object_ownership, ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].object_ownership`);
815
+ }
816
+ if (claim.factKind === "simulation_result") {
817
+ requireSourceEvidence(claim.sourceEvidenceId, SAFETY_CRITICAL_FACT_MATRIX.simulation_result, ["evidenceClaims", index, "sourceEvidenceId"], `evidenceClaims[${index}].simulation_result`);
818
+ if (claim.status === "success" && claim.missingFields.length !== 0) {
819
+ ctx.addIssue({
820
+ code: z.ZodIssueCode.custom,
821
+ path: ["evidenceClaims", index, "missingFields"],
822
+ message: "Successful simulation claim must not have missing required fields"
823
+ });
824
+ }
825
+ if (!WALLET_REVIEW_REQUIRED_SIMULATION_FIELDS.every((field) => claim.requiredFields.includes(field))) {
826
+ ctx.addIssue({
827
+ code: z.ZodIssueCode.custom,
828
+ path: ["evidenceClaims", index, "requiredFields"],
829
+ message: "Simulation claim must include every required simulation field"
830
+ });
831
+ }
832
+ if (claim.status !== "success" && claim.failureReason === undefined) {
833
+ ctx.addIssue({
834
+ code: z.ZodIssueCode.custom,
835
+ path: ["evidenceClaims", index, "failureReason"],
836
+ message: "Failed or unavailable simulation claim requires failureReason"
837
+ });
838
+ }
839
+ if (claim.status === "success" && claim.failureReason !== undefined) {
840
+ ctx.addIssue({
841
+ code: z.ZodIssueCode.custom,
842
+ path: ["evidenceClaims", index, "failureReason"],
843
+ message: "Successful simulation claim must not include failureReason"
844
+ });
845
+ }
846
+ }
847
+ });
848
+ value.rawQuantities.forEach((quantity, index) => {
849
+ const amountClaim = requireClaim(quantity.amountClaimId, "raw_quantity_amount", ["rawQuantities", index, "amountClaimId"], `rawQuantities[${index}].amountClaimId`);
850
+ if (amountClaim?.factKind === "raw_quantity_amount") {
851
+ requireEqual(ctx, quantity.role, amountClaim.role, ["rawQuantities", index, "role"], `rawQuantities[${index}].role`);
852
+ requireEqual(ctx, quantity.rawAmount, amountClaim.rawAmount, ["rawQuantities", index, "rawAmount"], `rawQuantities[${index}].rawAmount`);
853
+ requireSameAsset(ctx, quantity.asset, amountClaim.asset, ["rawQuantities", index, "asset"], `rawQuantities[${index}].asset`);
854
+ }
855
+ const unitClaim = requireClaim(quantity.unit.unitClaimId, "unit_metadata", ["rawQuantities", index, "unit", "unitClaimId"], `rawQuantities[${index}].unit.unitClaimId`);
856
+ if (unitClaim?.factKind === "unit_metadata") {
857
+ requireEqual(ctx, quantity.unit.source, unitClaim.source, ["rawQuantities", index, "unit", "source"], `rawQuantities[${index}].unit.source`);
858
+ requireEqual(ctx, quantity.unit.decimals, unitClaim.decimals, ["rawQuantities", index, "unit", "decimals"], `rawQuantities[${index}].unit.decimals`);
859
+ if (quantity.asset.coinType !== undefined) {
860
+ requireEqual(ctx, quantity.asset.coinType, unitClaim.coinType, ["rawQuantities", index, "asset", "coinType"], `rawQuantities[${index}].asset.coinType`);
861
+ }
862
+ }
863
+ });
864
+ if (value.gas.gasBudgetRaw !== undefined) {
865
+ const gasBudgetClaim = requireClaim(value.gas.gasBudgetClaimId, "raw_quantity_amount", ["gas", "gasBudgetClaimId"], "gas.gasBudgetClaimId");
866
+ if (gasBudgetClaim?.factKind === "raw_quantity_amount") {
867
+ requireEqual(ctx, gasBudgetClaim.role, CONSUMER_INVARIANT_MATRIX.gasBudgetClaimId.role, ["gas", "gasBudgetClaimId"], "gas.gasBudgetClaimId role");
868
+ requireGasAsset(ctx, gasBudgetClaim.asset, CONSUMER_INVARIANT_MATRIX.gasBudgetClaimId.assetCoinType, ["gas", "gasBudgetClaimId"], "gas.gasBudgetClaimId asset");
869
+ requireEqual(ctx, value.gas.gasBudgetRaw, gasBudgetClaim.rawAmount, ["gas", "gasBudgetRaw"], "gas.gasBudgetRaw");
870
+ }
871
+ }
872
+ if (value.gas.gasUsedRaw !== undefined) {
873
+ const gasUsedClaim = requireClaim(value.gas.gasUsedClaimId, "raw_quantity_amount", ["gas", "gasUsedClaimId"], "gas.gasUsedClaimId");
874
+ if (gasUsedClaim?.factKind === "raw_quantity_amount") {
875
+ requireEqual(ctx, gasUsedClaim.role, CONSUMER_INVARIANT_MATRIX.gasUsedClaimId.role, ["gas", "gasUsedClaimId"], "gas.gasUsedClaimId role");
876
+ requireGasAsset(ctx, gasUsedClaim.asset, CONSUMER_INVARIANT_MATRIX.gasUsedClaimId.assetCoinType, ["gas", "gasUsedClaimId"], "gas.gasUsedClaimId asset");
877
+ requireEqual(ctx, value.gas.gasUsedRaw, gasUsedClaim.rawAmount, ["gas", "gasUsedRaw"], "gas.gasUsedRaw");
878
+ }
879
+ }
880
+ if (value.gas.unresolvedReason !== undefined) {
881
+ const unresolvedClaim = requireClaim(value.gas.unresolvedClaimId, "gas_unresolved_status", ["gas", "unresolvedClaimId"], "gas.unresolvedClaimId");
882
+ if (unresolvedClaim?.factKind === "gas_unresolved_status") {
883
+ requireEqual(ctx, unresolvedClaim.status, "unresolved", ["gas", "unresolvedClaimId"], "gas.unresolvedClaimId status");
884
+ requireEqual(ctx, value.gas.checkedAt, unresolvedClaim.checkedAt, ["gas", "checkedAt"], "gas.checkedAt");
885
+ requireEqual(ctx, value.gas.unresolvedReason, unresolvedClaim.reason, ["gas", "unresolvedReason"], "gas.unresolvedReason");
886
+ }
887
+ }
888
+ value.gas.gasObjects?.forEach((gasObject, index) => {
889
+ const ownershipClaim = requireClaim(gasObject.ownershipClaimId, "object_ownership", ["gas", "gasObjects", index, "ownershipClaimId"], `gas.gasObjects[${index}].ownershipClaimId`);
890
+ if (ownershipClaim?.factKind === "object_ownership") {
891
+ requireEqual(ctx, gasObject.objectId, ownershipClaim.objectId, ["gas", "gasObjects", index, "objectId"], `gas.gasObjects[${index}].objectId`);
892
+ requireEqual(ctx, gasObject.ownerAccount, ownershipClaim.ownerAccount, ["gas", "gasObjects", index, "ownerAccount"], `gas.gasObjects[${index}].ownerAccount`);
893
+ requireEqual(ctx, ownershipClaim.ownership, CONSUMER_INVARIANT_MATRIX.gasObjectOwnershipClaimId.ownership, ["gas", "gasObjects", index, "ownershipClaimId"], `gas.gasObjects[${index}].ownershipClaimId ownership`);
894
+ }
895
+ });
896
+ const expiryClaim = requireClaim(value.expiry.evidenceClaimId, "expiry_status", ["expiry", "evidenceClaimId"], "expiry.evidenceClaimId");
897
+ if (expiryClaim?.factKind === "expiry_status") {
898
+ requireEqual(ctx, value.expiry.status, expiryClaim.status, ["expiry", "status"], "expiry.status");
899
+ requireEqual(ctx, value.expiry.checkedAt, expiryClaim.checkedAt, ["expiry", "checkedAt"], "expiry.checkedAt");
900
+ if (value.expiry.status === "current" || value.expiry.status === "expired") {
901
+ requireEqual(ctx, value.expiry.expiresAt, expiryClaim.expiresAt, ["expiry", "expiresAt"], "expiry.expiresAt");
902
+ }
903
+ else {
904
+ requireEqual(ctx, value.expiry.reason, expiryClaim.reason, ["expiry", "reason"], "expiry.reason");
905
+ }
906
+ }
907
+ if (value.slippageOrMinOut.quoteEvidenceClaimId !== undefined) {
908
+ const quoteClaim = requireClaim(value.slippageOrMinOut.quoteEvidenceClaimId, "quote_min_out", ["slippageOrMinOut", "quoteEvidenceClaimId"], "slippageOrMinOut.quoteEvidenceClaimId");
909
+ if (quoteClaim?.factKind === "quote_min_out") {
910
+ requireEqual(ctx, value.slippageOrMinOut.quoteEvidenceId, quoteClaim.quoteEvidenceId, ["slippageOrMinOut", "quoteEvidenceId"], "slippageOrMinOut.quoteEvidenceId");
911
+ requireEqual(ctx, value.slippageOrMinOut.minOutRaw, quoteClaim.minOutRaw, ["slippageOrMinOut", "minOutRaw"], "slippageOrMinOut.minOutRaw");
912
+ }
913
+ }
914
+ if (value.slippageOrMinOut.minOutRaw !== undefined) {
915
+ const matchingMinOutQuantity = value.rawQuantities.some((quantity) => quantity.role === "minimum_output" &&
916
+ quantity.rawAmount === value.slippageOrMinOut.minOutRaw);
917
+ if (!matchingMinOutQuantity) {
918
+ ctx.addIssue({
919
+ code: z.ZodIssueCode.custom,
920
+ path: ["slippageOrMinOut", "minOutRaw"],
921
+ message: "slippageOrMinOut.minOutRaw must match a minimum_output rawQuantities entry"
922
+ });
923
+ }
924
+ }
925
+ if (value.slippageOrMinOut.policyEvidenceClaimId !== undefined) {
926
+ const policyClaim = requireClaim(value.slippageOrMinOut.policyEvidenceClaimId, "slippage_policy", ["slippageOrMinOut", "policyEvidenceClaimId"], "slippageOrMinOut.policyEvidenceClaimId");
927
+ if (policyClaim?.factKind === "slippage_policy") {
928
+ requireEqual(ctx, value.slippageOrMinOut.policySource, policyClaim.policySource, ["slippageOrMinOut", "policySource"], "slippageOrMinOut.policySource");
929
+ requireEqual(ctx, value.slippageOrMinOut.maxSlippageBps, policyClaim.maxSlippageBps, ["slippageOrMinOut", "maxSlippageBps"], "slippageOrMinOut.maxSlippageBps");
930
+ if (policyClaim.policySource === "adapter_policy_from_quote_evidence") {
931
+ requireEqual(ctx, value.slippageOrMinOut.minOutRaw, policyClaim.minOutRaw, ["slippageOrMinOut", "minOutRaw"], "slippageOrMinOut.minOutRaw");
932
+ }
933
+ }
934
+ }
935
+ value.objectOwnership.objects.forEach((object, index) => {
936
+ const ownershipClaim = requireClaim(object.evidenceClaimId, "object_ownership", ["objectOwnership", "objects", index, "evidenceClaimId"], `objectOwnership.objects[${index}].evidenceClaimId`);
937
+ if (ownershipClaim?.factKind === "object_ownership") {
938
+ requireEqual(ctx, object.objectId, ownershipClaim.objectId, ["objectOwnership", "objects", index, "objectId"], `objectOwnership.objects[${index}].objectId`);
939
+ requireEqual(ctx, value.objectOwnership.ownerAccount, ownershipClaim.ownerAccount, ["objectOwnership", "ownerAccount"], "objectOwnership.ownerAccount");
940
+ requireEqual(ctx, object.ownership, ownershipClaim.ownership, ["objectOwnership", "objects", index, "ownership"], `objectOwnership.objects[${index}].ownership`);
941
+ }
942
+ });
943
+ const simulationClaim = requireClaim(value.simulation.evidenceClaimId, "simulation_result", ["simulation", "evidenceClaimId"], "simulation.evidenceClaimId");
944
+ if (simulationClaim?.factKind === "simulation_result") {
945
+ requireEqual(ctx, value.simulation.provider, simulationClaim.provider, ["simulation", "provider"], "simulation.provider");
946
+ requireEqual(ctx, value.simulation.checksEnabled, simulationClaim.checksEnabled, ["simulation", "checksEnabled"], "simulation.checksEnabled");
947
+ requireEqual(ctx, value.simulation.simulatedAt, simulationClaim.simulatedAt, ["simulation", "simulatedAt"], "simulation.simulatedAt");
948
+ requireEqual(ctx, value.simulation.status, simulationClaim.status, ["simulation", "status"], "simulation.status");
949
+ requireSameStringSet(ctx, value.simulation.requiredFields, simulationClaim.requiredFields, ["simulation", "requiredFields"], "simulation.requiredFields");
950
+ requireSameStringSet(ctx, value.simulation.missingFields, simulationClaim.missingFields, ["simulation", "missingFields"], "simulation.missingFields");
951
+ requireEqual(ctx, value.simulation.failureReason, simulationClaim.failureReason, ["simulation", "failureReason"], "simulation.failureReason");
952
+ }
953
+ }).superRefine((value, ctx) => {
954
+ // Contract invariant: human review, review-time simulation, and transaction
955
+ // material commitment must all reference the same Sui transaction digest.
956
+ // Reuse requireEqual so commitment checks match the evidence-claim bindings.
957
+ const handoffDigest = value.transactionMaterialCommitment;
958
+ requireEqual(ctx, value.humanReadableReview.boundToCommitment, handoffDigest, ["humanReadableReview", "boundToCommitment"], "humanReadableReview.boundToCommitment");
959
+ requireEqual(ctx, value.simulation.boundToCommitment, handoffDigest, ["simulation", "boundToCommitment"], "simulation.boundToCommitment");
960
+ });
961
+ export const ptbVisualizationArtifactSchema = z.object({
962
+ contractVersion: z.literal(PTB_VISUALIZATION_CONTRACT_VERSION),
963
+ artifactKind: z.literal("ptb_visualization"),
964
+ generatedAt: isoUtcStringSchema,
965
+ source: z.object({
966
+ adapterId: z.string().min(1).max(120),
967
+ planId: z.string().min(1).max(120).optional(),
968
+ sourceKind: z.enum(["review_time_generated_transaction_kind", "review_time_ir", "renderer_model"]),
969
+ authority: z.literal("visualization_only_not_wallet_authorization"),
970
+ renderer: z.object({
971
+ name: z.string().min(1).max(120),
972
+ packageName: z.string().min(1).max(120).optional(),
973
+ version: z.string().min(1).max(80).optional()
974
+ }).strict().optional()
975
+ }).strict(),
976
+ mermaid: z.object({
977
+ diagramType: z.literal("flowchart"),
978
+ text: displayTextWithoutExecutableMaterial(20_000, "mermaid.text")
979
+ }).strict(),
980
+ diagnostics: z.array(z.object({
981
+ severity: z.enum(["info", "warning", "error"]),
982
+ code: z.string().min(1).max(120),
983
+ message: displayTextWithoutExecutableMaterial(512, "diagnostics.message"),
984
+ source: z.enum(["adapter", "renderer", "schema", "simulation"])
985
+ }).strict()).default([]),
986
+ unsupportedUse: z.array(z.enum(PTB_VISUALIZATION_REQUIRED_UNSUPPORTED_USES)).min(1),
987
+ executableMaterial: z.object({
988
+ included: z.literal(false),
989
+ policy: z.literal("mcp_and_review_ui_outputs_must_not_include_executable_transaction_material")
990
+ }).strict()
991
+ }).strict().superRefine((value, ctx) => {
992
+ requireAllValues(ctx, value.unsupportedUse, PTB_VISUALIZATION_REQUIRED_UNSUPPORTED_USES, ["unsupportedUse"], "unsupportedUse");
993
+ });