@zktx.io/sui-mcp 0.5.0

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 (218) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSES/@mysten-bcs-2.0.5-Apache-2.0.txt +205 -0
  3. package/LICENSES/@mysten-sui-2.17.0-Apache-2.0.txt +201 -0
  4. package/LICENSES/@mysten-utils-0.3.3-Apache-2.0.txt +205 -0
  5. package/LICENSES/fancy-canvas-2.1.0-MIT.txt +7 -0
  6. package/LICENSES/lightweight-charts-5.2.0-NOTICE.txt +2 -0
  7. package/README.md +288 -0
  8. package/dist/adapters/adapterLifecycleValidators.js +5 -0
  9. package/dist/adapters/adapterPromptSurfaces.js +60 -0
  10. package/dist/adapters/deepbook/deepbookHumanReviewProducer.js +178 -0
  11. package/dist/adapters/deepbook/deepbookQuotePolicy.js +112 -0
  12. package/dist/adapters/deepbook/deepbookReviewEvidence.js +507 -0
  13. package/dist/adapters/deepbook/deepbookReviewLifecycle.js +85 -0
  14. package/dist/adapters/deepbook/deepbookSwapIntent.js +79 -0
  15. package/dist/adapters/deepbook/deepbookTransactionMaterialProducer.js +254 -0
  16. package/dist/adapters/intentPlanFactories.js +51 -0
  17. package/dist/adapters/reviewAdapters.js +47 -0
  18. package/dist/core/action/adapterLifecycleValidation.js +12 -0
  19. package/dist/core/action/contractNameRegistry.js +151 -0
  20. package/dist/core/action/forbiddenFields.js +43 -0
  21. package/dist/core/action/humanReadableReviewEvidence.js +193 -0
  22. package/dist/core/action/humanReadableReviewProjectionVerifier.js +29 -0
  23. package/dist/core/action/ptbVisualizationProducer.js +71 -0
  24. package/dist/core/action/receiptPtbGraph.js +29 -0
  25. package/dist/core/action/reviewCheckResults.js +6 -0
  26. package/dist/core/action/reviewStateValidation.js +11 -0
  27. package/dist/core/action/reviewTimeSimulationEvidence.js +470 -0
  28. package/dist/core/action/schemas.js +491 -0
  29. package/dist/core/action/signableAdapterContract.js +998 -0
  30. package/dist/core/action/suiChainReceiptEvidence.js +106 -0
  31. package/dist/core/action/suiChainReceiptMapping.js +107 -0
  32. package/dist/core/action/suiChainReceiptReader.js +211 -0
  33. package/dist/core/action/suiChainReceiptVerifier.js +178 -0
  34. package/dist/core/action/swapHumanReadableReviewProjection.js +130 -0
  35. package/dist/core/action/swapQuotePolicyEvidence.js +271 -0
  36. package/dist/core/action/transactionFunding.js +244 -0
  37. package/dist/core/action/transactionObjectOwnershipEvidence.js +256 -0
  38. package/dist/core/action/transactionObjectOwnershipProducer.js +323 -0
  39. package/dist/core/action/types.js +33 -0
  40. package/dist/core/action/walletReviewContractAssembler.js +286 -0
  41. package/dist/core/activity/accountAssetTimeline.js +157 -0
  42. package/dist/core/activity/accountAssetTimelineUsdcReferences.js +120 -0
  43. package/dist/core/activity/activityStore.js +16 -0
  44. package/dist/core/activity/externalActivityCoverage.js +76 -0
  45. package/dist/core/activity/externalActivityTransactionStream.js +82 -0
  46. package/dist/core/activity/localDataService.js +296 -0
  47. package/dist/core/activity/localDataTypes.js +11 -0
  48. package/dist/core/activity/localDataValidation.js +439 -0
  49. package/dist/core/activity/schemaVersion.js +2 -0
  50. package/dist/core/activity/sqliteActivityStore.js +1068 -0
  51. package/dist/core/activity/sqliteActivityStoreRows.js +389 -0
  52. package/dist/core/activity/sqliteActivityStoreSchema.js +367 -0
  53. package/dist/core/activity/sqliteActivityStoreTypes.js +5 -0
  54. package/dist/core/activity/suiFunctionTarget.js +43 -0
  55. package/dist/core/activity/transactionActivityAccountEffects.js +186 -0
  56. package/dist/core/activity/transactionActivityAnalysis.js +295 -0
  57. package/dist/core/activity/transactionActivityClassifier.js +306 -0
  58. package/dist/core/activity/transactionActivityDetails.js +229 -0
  59. package/dist/core/activity/transactionActivityProtocolRules.js +218 -0
  60. package/dist/core/activity/transactionActivityScanPolicy.js +170 -0
  61. package/dist/core/activity/transactionActivityService.js +379 -0
  62. package/dist/core/activity/transactionActivityTypes.js +18 -0
  63. package/dist/core/eventlog/sink.js +35 -0
  64. package/dist/core/evidence/settlementFamilies.js +85 -0
  65. package/dist/core/evidence/userAnswerUse.js +1 -0
  66. package/dist/core/numeric/rawU64.js +63 -0
  67. package/dist/core/preferences/preferencesStore.js +26 -0
  68. package/dist/core/preferences/sqlitePreferencesRepository.js +136 -0
  69. package/dist/core/proposal/externalProposalReview.js +347 -0
  70. package/dist/core/proposal/schemas.js +208 -0
  71. package/dist/core/proposal/types.js +35 -0
  72. package/dist/core/read/amounts.js +14 -0
  73. package/dist/core/read/coinMetadata.js +60 -0
  74. package/dist/core/read/deepbookOfficialIndexerSource.js +373 -0
  75. package/dist/core/read/deepbookRawQuoteClient.js +86 -0
  76. package/dist/core/read/deepbookReadHelpers.js +321 -0
  77. package/dist/core/read/deepbookRegistry.js +157 -0
  78. package/dist/core/read/deepbookSourceOwners.js +159 -0
  79. package/dist/core/read/deepbookUsdcChartService.js +342 -0
  80. package/dist/core/read/intentEvidenceResponseFormatting.js +228 -0
  81. package/dist/core/read/readCardInputs.js +19 -0
  82. package/dist/core/read/readCardResult.js +40 -0
  83. package/dist/core/read/readResponseGuidance.js +402 -0
  84. package/dist/core/read/readService.js +1639 -0
  85. package/dist/core/read/readServiceTypes.js +88 -0
  86. package/dist/core/read/settlementParityFormatting.js +82 -0
  87. package/dist/core/read/walletReadHelpers.js +99 -0
  88. package/dist/core/review/reviewChecks.js +45 -0
  89. package/dist/core/review/reviewComputation.js +38 -0
  90. package/dist/core/review/reviewComputationResult.js +87 -0
  91. package/dist/core/session/cardSession.js +31 -0
  92. package/dist/core/session/cardSessionStore.js +204 -0
  93. package/dist/core/session/keyedRecordStore.js +18 -0
  94. package/dist/core/session/liveReviewSessionContract.js +3 -0
  95. package/dist/core/session/localSession.js +31 -0
  96. package/dist/core/session/privateReviewArtifacts.js +75 -0
  97. package/dist/core/session/reviewValidity.js +49 -0
  98. package/dist/core/session/sessionErrors.js +9 -0
  99. package/dist/core/session/sessionRecordStore.js +40 -0
  100. package/dist/core/session/sessionStore.js +655 -0
  101. package/dist/core/session/settingsSession.js +1 -0
  102. package/dist/core/session/settingsSessions.js +45 -0
  103. package/dist/core/session/sqliteCardStore.js +88 -0
  104. package/dist/core/session/sqliteSessionStore.js +213 -0
  105. package/dist/core/session/sqliteTransactionMaterialStore.js +64 -0
  106. package/dist/core/session/sqliteWalletWorkflowStore.js +821 -0
  107. package/dist/core/session/status.js +60 -0
  108. package/dist/core/session/transactionMaterialStore.js +221 -0
  109. package/dist/core/session/transactionRequest.js +72 -0
  110. package/dist/core/session/wait.js +79 -0
  111. package/dist/core/session/walletConnection.js +92 -0
  112. package/dist/core/session/walletRuntime.js +38 -0
  113. package/dist/core/session/walletWorkflow.js +608 -0
  114. package/dist/core/session/workflowState.js +80 -0
  115. package/dist/core/session/workflowView.js +150 -0
  116. package/dist/core/suiAddress.js +18 -0
  117. package/dist/core/suiEndpoint.js +72 -0
  118. package/dist/mcp/activeAccountResponse.js +24 -0
  119. package/dist/mcp/prompts.js +146 -0
  120. package/dist/mcp/registerTool.js +19 -0
  121. package/dist/mcp/resources.js +72 -0
  122. package/dist/mcp/responseGuidance.js +326 -0
  123. package/dist/mcp/result.js +17 -0
  124. package/dist/mcp/schemas.js +11 -0
  125. package/dist/mcp/server.js +32 -0
  126. package/dist/mcp/serverInfo.js +131 -0
  127. package/dist/mcp/toolErrors.js +118 -0
  128. package/dist/mcp/toolNames.js +58 -0
  129. package/dist/mcp/tools/account/index.js +44 -0
  130. package/dist/mcp/tools/action/prepareSuiActionReview.js +126 -0
  131. package/dist/mcp/tools/read/commonSchemas.js +43 -0
  132. package/dist/mcp/tools/read/deepbookReadTools.js +686 -0
  133. package/dist/mcp/tools/read/index.js +14 -0
  134. package/dist/mcp/tools/read/readToolHelpers.js +97 -0
  135. package/dist/mcp/tools/read/reviewActivityTools.js +179 -0
  136. package/dist/mcp/tools/read/serverStatusTools.js +100 -0
  137. package/dist/mcp/tools/read/transactionActivityOutput.js +371 -0
  138. package/dist/mcp/tools/read/transactionActivityTools.js +858 -0
  139. package/dist/mcp/tools/read/walletReadTools.js +734 -0
  140. package/dist/mcp/tools/session/executionResultTools.js +44 -0
  141. package/dist/mcp/tools/session/index.js +8 -0
  142. package/dist/mcp/tools/session/shared.js +36 -0
  143. package/dist/mcp/tools/session/statusTools.js +69 -0
  144. package/dist/mcp/tools/session/walletConnectionTools.js +69 -0
  145. package/dist/mcp/tools/settings/index.js +66 -0
  146. package/dist/mcp-app/account.html +3133 -0
  147. package/dist/mcp-app/account.notices.txt +973 -0
  148. package/dist/mcp-app/chart.html +3354 -0
  149. package/dist/mcp-app/chart.notices.txt +1194 -0
  150. package/dist/mcp-app/connect.html +3179 -0
  151. package/dist/mcp-app/connect.notices.txt +1012 -0
  152. package/dist/mcp-app/receipt.html +8430 -0
  153. package/dist/mcp-app/receipt.notices.txt +3549 -0
  154. package/dist/mcp-app/review.html +8430 -0
  155. package/dist/mcp-app/review.notices.txt +3549 -0
  156. package/dist/mcp-ui/contracts.js +31 -0
  157. package/dist/mcp-ui/readCards.js +28 -0
  158. package/dist/mcp-ui/tools.js +134 -0
  159. package/dist/review-app/brand-dark.svg +1 -0
  160. package/dist/review-app/brand-light.svg +1 -0
  161. package/dist/review-app/favicon.svg +1 -0
  162. package/dist/review-app/settings.css +1 -0
  163. package/dist/review-app/settings.js +1 -0
  164. package/dist/review-app/ui.css +809 -0
  165. package/dist/review-server/assets.js +48 -0
  166. package/dist/review-server/html.js +45 -0
  167. package/dist/review-server/http.js +47 -0
  168. package/dist/review-server/middleware/hostOrigin.js +48 -0
  169. package/dist/review-server/middleware/reviewToken.js +7 -0
  170. package/dist/review-server/reviewServerPolicy.js +1 -0
  171. package/dist/review-server/server.js +72 -0
  172. package/dist/review-server/settingsApi.js +158 -0
  173. package/dist/runtime/application.js +203 -0
  174. package/dist/runtime/config.js +97 -0
  175. package/dist/runtime/localSettingsService.js +198 -0
  176. package/dist/runtime/logger.js +66 -0
  177. package/dist/runtime/reviewDependencies.js +58 -0
  178. package/dist/runtime/reviewServerAcquire.js +93 -0
  179. package/dist/runtime/runtimeTermination.js +60 -0
  180. package/dist/runtime/shared/authenticatedFetch.js +127 -0
  181. package/dist/runtime/shared/control.js +93 -0
  182. package/dist/runtime/shared/dataAccess.js +66 -0
  183. package/dist/runtime/shared/mcpHttp.js +84 -0
  184. package/dist/runtime/shared/ownerLease.js +50 -0
  185. package/dist/runtime/shared/server.js +98 -0
  186. package/dist/runtime/shared/stdio.js +113 -0
  187. package/dist/runtime/smokeMainnetRead.js +391 -0
  188. package/dist/runtime/smokeMainnetReadAssertions.js +306 -0
  189. package/dist/runtime/smokeReview.js +40 -0
  190. package/dist/runtime/start.js +90 -0
  191. package/dist/runtime/suiEndpoint.js +97 -0
  192. package/dist/runtime/suiTransactionGraphqlMapping.js +200 -0
  193. package/dist/runtime/suiTransactionGraphqlQueries.js +231 -0
  194. package/dist/runtime/suiTransactionGraphqlSource.js +148 -0
  195. package/dist/runtime/walletConnectConfig.js +3 -0
  196. package/dist/runtime/walletConnectStorage.js +99 -0
  197. package/dist/runtime/walletConnectTransport.js +128 -0
  198. package/dist/runtime/walletSdkChild.js +3 -0
  199. package/dist/runtime/walletSdkChildRuntime.js +160 -0
  200. package/dist/runtime/walletSdkIpc.js +26 -0
  201. package/dist/runtime/walletSdkProcess.js +358 -0
  202. package/docs/AGENT_BEHAVIOR.md +524 -0
  203. package/docs/AGENT_DEVELOPMENT_POLICY.md +815 -0
  204. package/docs/FRONTEND_POLICY.md +534 -0
  205. package/docs/LOCAL_DB_ARCHITECTURE.md +381 -0
  206. package/docs/MCP_SETUP.md +742 -0
  207. package/docs/MCP_TOOLS.md +1318 -0
  208. package/docs/SDK_API.md +206 -0
  209. package/docs/SIGNABLE_ADAPTER_CONTRACT.md +396 -0
  210. package/docs/TRANSACTION_ACTIVITY_LOG.md +194 -0
  211. package/docs/UTILITY_INDEX.md +275 -0
  212. package/docs/WALLET_CONNECTION.md +238 -0
  213. package/docs/golden-scenarios/BEHAVIOR_MATRIX.md +166 -0
  214. package/docs/golden-scenarios/INTENT_EVIDENCE_GOLDEN_ANSWERS.md +161 -0
  215. package/docs/golden-scenarios/INTENT_EVIDENCE_MATRIX.md +259 -0
  216. package/package.json +79 -0
  217. package/protocols/deepbook-margin.md +15 -0
  218. package/protocols/deepbook-v3.md +24 -0
@@ -0,0 +1,206 @@
1
+ # SDK API Verification
2
+
3
+ This document records the pinned SDK APIs used by the current runtime. The source of truth is the installed package source in `node_modules`, not memory or external summaries.
4
+
5
+ ## Package Versions
6
+
7
+ - `@modelcontextprotocol/ext-apps`: `1.7.5`
8
+ - `@modelcontextprotocol/sdk`: `1.29.0`
9
+ - `@mysten/sui`: `2.17.0`
10
+ - `@mysten/deepbook-v3`: `1.3.6`
11
+ - `@walletconnect/sign-client`, `@walletconnect/types`, `@walletconnect/utils`: `2.23.10`
12
+ - `qrcode`: `1.5.4`
13
+ - `@zktx.io/ptb-model`: `0.5.0`
14
+ - `mermaid`: `11.12.0`
15
+
16
+ ## MCP Apps
17
+
18
+ `@modelcontextprotocol/ext-apps` is pinned to `1.7.5`, with MCP SDK `1.29.0`. The server uses `registerAppTool`, `registerAppResource` and `getUiCapability`; the view uses `App` for host-mediated calls and teardown. Account, Receipt, Chart, Connect and Review are separate self-contained resources, so an account card does not load the PTB or chart renderer. The server keeps app-only permissions out of model content.
19
+
20
+ The shared server uses the pinned MCP SDK Streamable HTTP transport behind authenticated loopback access. Stdio clients forward tool, resource and prompt requests with their original client identity and capabilities. Ordinary MCP input schemas remain unchanged by the transport; the 64 KiB card/HTTP input limit includes the card call envelope.
21
+
22
+ ## WalletConnect Runtime
23
+
24
+ The backend passes the product identifier from `src/runtime/walletConnectConfig.ts`
25
+ to the pinned `SignClient.init`. The shared runtime's configuration identity uses
26
+ the same value. There is no user project ID setting or environment override.
27
+ Identifier-format validation remains before SDK initialization. Initialization,
28
+ restoration and runtime-state failures remain separate from wallet approval and
29
+ transaction results; public diagnostics do not include raw SDK error bodies.
30
+
31
+ ## Sui gRPC Client
32
+
33
+ Verified from `node_modules/@mysten/sui/src/grpc/index.ts`, `client.ts`, `core.ts`, and `node_modules/@mysten/sui/src/client/types.ts`.
34
+
35
+ - Import path: `@mysten/sui/grpc`
36
+ - Client: `SuiGrpcClient`
37
+ - Constructor input includes:
38
+ - `network`
39
+ - `baseUrl`
40
+ - optional `fetchInit`
41
+ - or custom `transport`
42
+ - Runtime construction:
43
+
44
+ ```ts
45
+ new SuiGrpcClient({
46
+ baseUrl: "https://fullnode.mainnet.sui.io:443",
47
+ network: "mainnet"
48
+ });
49
+ ```
50
+
51
+ Confirmed methods:
52
+
53
+ | Method | Signature Source | Notes |
54
+ | --- | --- | --- |
55
+ | `client.core.getChainIdentifier()` | `GrpcCoreClient.getChainIdentifier(_options?)` | Returns `{ chainIdentifier: string }`. |
56
+ | `client.core.listBalances(options)` | `GrpcCoreClient.listBalances(options)` | `options.owner` is required; `options.cursor` and `options.limit` are available. Returns `{ balances, hasNextPage, cursor }`. |
57
+ | `client.core.getCoinMetadata(options)` | `GrpcCoreClient.getCoinMetadata(options)` | `options.coinType` is required. Returns `{ coinMetadata }`; metadata can be `null`. The gRPC implementation resolves type through MVR before calling `stateService.getCoinInfo`; the pinned gRPC implementation catches `getCoinInfo` failures and returns `coinMetadata: null`, so callers cannot distinguish those failures from missing metadata through this method alone. |
58
+ | `client.core.simulateTransaction(options)` | `GrpcCoreClient.simulateTransaction(options)` | Accepts `transaction`, optional `include`, optional `checksEnabled`. |
59
+
60
+ `SimulateTransactionOptions.checksEnabled` defaults to enabled and can be set to `false` for debug/read inspection. Read-only DeepBook SDK methods use simulation internally and must not be presented as signing readiness.
61
+
62
+ For review-time transaction simulation, use the public gRPC `client.transactionExecutionService.simulateTransaction` with validation checks enabled (`checks: ENABLED`), `doGasSelection: true`, and the complete stored BCS transaction. In the pinned core API, `doGasSelection: false` can let the node inject mock gas for an empty gas payment, changing the simulated digest. Require returned BCS to equal the submitted bytes and require the effects digest to match; selection must not change the reviewed material. Decode transaction facts from the identical returned BCS. Request effects, balance changes and object id/type facts, and require the normalized `effects`, `balanceChanges`, `objectTypes` and `transaction` evidence. Missing required fields must fail closed. Returned BCS is only a private equality check and must not enter public or stored review evidence; raw transaction bytes are not an MCP or review-app output. `commandResults` remains scoped to read-only DeepBook raw quote extraction using `client.core.simulateTransaction`, not swap review simulation evidence. Failed simulations are blocked pre-signing review facts, not wallet rejection, transaction submission failure, or automatic transient retry evidence. A thrown simulation call is refreshable only when it is classified as a transport, RPC, timeout, or endpoint availability failure; malformed transaction material, request-shape bugs, incomplete results, and adapter defects remain blocked.
63
+
64
+ Only an explicit `effects.status.success: false` reports simulation failure. A missing transaction, effects, status, or boolean success value means the response cannot establish an outcome. Incomplete or inconsistent evidence blocks the review with a fixed explanation; internal validation and JavaScript error messages are not public review facts. A `success: true` response still requires all material and evidence checks above.
65
+
66
+ During transaction building, the SDK's `SimulationError.executionError` does
67
+ not preserve every gRPC error kind. A build error can establish a returned
68
+ simulation rejection without establishing a specific funding shortfall. Build
69
+ error text is not used to infer insufficient gas or coin balance. Explicit
70
+ shortfalls remain available from verified funding reads and the typed error
71
+ kinds returned directly by review-time simulation.
72
+
73
+ ## DeepBook Read Methods
74
+
75
+ Verified from `node_modules/@mysten/deepbook-v3/src/client.ts` and `node_modules/@mysten/deepbook-v3/src/types/index.ts`.
76
+
77
+ - Import path: `@mysten/deepbook-v3`
78
+ - Client: `DeepBookClient`
79
+ - Constructor requires:
80
+ - `client`
81
+ - `address`
82
+ - `network`
83
+ - Constructor also accepts optional configured `balanceManagers`; Sui MCP uses this only to register a user-supplied `managerAddress` as an ephemeral SDK BalanceManager key for account-bound inventory detail reads.
84
+
85
+ The `address` is used by the SDK as the transaction simulation sender for read queries. For sender-independent DeepBook orderbook, raw-quantity quote, and display-amount quote reads, Sui MCP supplies an internal mainnet placeholder address. This placeholder is not user identity and must not be represented as wallet authorization.
86
+
87
+ Account-bound DeepBook reads, such as `read.summarize_deepbook_account_inventory`, use the active account address as the simulation sender. The product filters manager detail reads through on-chain `getBalanceManagerIds(owner)` discovery before calling account-bound detail methods; this is active read context, not signing authorization or custody.
88
+
89
+ Confirmed methods:
90
+
91
+ | Method | Return Type | Used For |
92
+ | --- | --- | --- |
93
+ | `midPrice(poolKey)` | `Promise<number>` | Orderbook context. |
94
+ | `poolBookParams(poolKey)` | `Promise<PoolBookParams>` | Tick, lot, and min size context. |
95
+ | `getLevel2TicksFromMid(poolKey, ticks)` | `Promise<Level2TicksFromMid>` | Bid/ask levels around mid price. |
96
+ | `deepBook.getQuoteQuantityOut(poolKey, baseQuantity)` | Transaction builder thunk | Base-to-quote quantity quote. Sui MCP passes positive raw input quantities that fit the SDK `u64` argument and parses the simulated raw `u64` return values directly. |
97
+ | `deepBook.getBaseQuantityOut(poolKey, quoteQuantity)` | Transaction builder thunk | Quote-to-base quantity quote. Sui MCP passes positive raw input quantities that fit the SDK `u64` argument and parses the simulated raw `u64` return values directly. |
98
+ | `getBalanceManagerIds(owner)` | `Promise<string[]>` | Active-account BalanceManager discovery. |
99
+ | `accountExists(poolKey, managerKey)` | `Promise<boolean>` | Gate before account-bound detail reads. |
100
+ | `account(poolKey, managerKey)` | `Promise<AccountInfo>` | Display-like account ledger and rebate inventory. Not raw/signable quantity. |
101
+ | `lockedBalance(poolKey, balanceManagerKey)` | `Promise<LockedBalances>` | Display-like balances tied to open orders. Not withdrawable/spendable readiness. |
102
+ | `accountOpenOrders(poolKey, managerKey)` | `Promise<string[]>` | Open order ID inventory; Sui MCP caps returned IDs in its public response. |
103
+
104
+ Relevant return shapes:
105
+
106
+ ```ts
107
+ type PoolBookParams = {
108
+ tickSize: number;
109
+ lotSize: number;
110
+ minSize: number;
111
+ };
112
+
113
+ type Level2TicksFromMid = {
114
+ bid_prices: number[];
115
+ bid_quantities: number[];
116
+ ask_prices: number[];
117
+ ask_quantities: number[];
118
+ };
119
+
120
+ type QuoteQuantityOut = {
121
+ baseQuantity: number;
122
+ baseOut: number;
123
+ quoteOut: number;
124
+ deepRequired: number;
125
+ };
126
+
127
+ type BaseQuantityOut = {
128
+ quoteQuantity: number;
129
+ baseOut: number;
130
+ quoteOut: number;
131
+ deepRequired: number;
132
+ };
133
+ ```
134
+
135
+ The pinned SDK accepts `number | bigint` quote inputs. Its high-level quote query objects include an input echo field (`baseQuantity` or `quoteQuantity`) produced with `Number(inputRaw)`, plus display quote fields (`baseOut`, `quoteOut`, and `deepRequired`) produced after scalar division and `Number(...)` conversion. Sui MCP does not use those high-level query objects as the canonical quote source for adapter preparation. It uses the pinned SDK transaction builder quote functions, requests `client.core.simulateTransaction` command results, and parses raw `u64` return values. The simulated public Move entrypoint is `pool::get_quote_quantity_out` for base-to-quote reads and `pool::get_base_quantity_out` for quote-to-base reads; both delegate to `pool::get_quantity_out`, whose official Move source defines the return order as `base_quantity_out`, `quote_quantity_out`, and `deep_quantity_required`. Public `quote` fields are exact decimal display strings derived from those raw values through pinned DeepBook scalars; `rawQuote` carries the raw evidence. `read.quote_deepbook_action` marks the input as raw `u64`, while `read.quote_deepbook_display_amount` marks the input as a source display amount converted to raw `u64`. Raw quote evidence is not an effective price, price-impact calculation, quote-vs-mid slippage calculation, venue comparison, best-route claim, fiat cash-out estimate, external market lookup, USDC/USD peg assumption, P&L, cost basis, final min-out, signing data, or signing readiness. The account-bound DeepBook review may derive a fresh raw quote policy from this evidence and use that derived policy for local unsigned transaction material build, while keeping bytes private to the backend until a scoped user selection admits a WalletConnect request for that reviewed revision. MCP and ordinary review-status outputs still do not contain transaction bytes, signing data, or signing readiness. When the digest commitment stage completes, it is derived from the locally stored transaction bytes through pinned SDK `Transaction.from(...).getDigest()` and remains an internal binding, not a public signing artifact.
136
+
137
+ ## Runtime Boundary
138
+
139
+ - JSON-RPC client imports are not used.
140
+ - Sui gRPC and GraphQL endpoints are resolved from local SQLite settings by default. `SUI_GRPC_URL` and `SUI_GRAPHQL_URL` are advanced temporary overrides and do not mutate stored settings.
141
+ - Sui gRPC URLs must include an explicit port and no credentials, path, query string, or fragment.
142
+ - Sui GraphQL URLs must use `https` and must not include credentials, query string, or fragment.
143
+ - The gRPC endpoint is verified during runtime startup. The GraphQL endpoint is verified when saved, imported, or first used by Sui activity tools.
144
+ - `fetchedAt` fields are ISO 8601 UTC strings produced by `new Date().toISOString()`.
145
+ - Read-only tools may inspect mainnet state but must not create signable transaction material.
146
+
147
+ ## WalletConnect and signature verification
148
+
149
+ The SDK child initializes pinned SignClient with its public `storage` injection,
150
+ private session persistence, silent SDK logging and telemetry disabled. It uses
151
+ `connect`, `session.getAll`, `session_update/session_delete/session_expire` events,
152
+ and `request` on chain `sui:mainnet`, method `sui_signTransaction`.
153
+ Pinned `session_event` does not update approved namespaces itself: account/chain
154
+ selection events explicitly invalidate stored review/submission authority even
155
+ when the approved account set stays unchanged. Requests carry
156
+ `{ transaction: <stored BCS base64>, address }`; responses require
157
+ `{ transactionBytes: <BCS base64>, signature }`. No SDK source patch or automatic
158
+ sign-and-execute fallback is used.
159
+
160
+ The backend reconstructs the returned transaction with `Transaction.from`,
161
+ recomputes its digest and calls pinned `verifyTransactionSignature` with the
162
+ admitted address and verified Sui client (including schemes requiring online
163
+ verification). Submission uses `client.core.executeTransaction` exactly once
164
+ per admitted attempt. `waitForTransaction` supplies separately verified chain
165
+ facts; its absence/timeout does not prove execution failure.
166
+
167
+ SDK session storage persists only the pinned connection namespaces. History,
168
+ requests and unknown queue keys are volatile. The SDK has no supported complete
169
+ in-process disposal; its owner process lifetime bounds callbacks and storage.
170
+ The parent uses a fixed packaged Node child entrypoint and private versioned IPC.
171
+ Only the SDK child owns SDK storage. The supervisor fences a terminating run,
172
+ sends SIGKILL to its owned child and waits for actual exit. Its explicit
173
+ replacement primitive remains private infrastructure; Connect and Settings do
174
+ not expose a restart command. Closing relay transport or receiving an IPC disconnection is not
175
+ evidence that the SDK operation ended. No SDK private teardown, source patch,
176
+ automatic financial retry or overlapping storage writer is used.
177
+
178
+ Snapshots and per-session versions distinguish present, absent and unusable
179
+ sessions. Source inspection failure disables the service instead of becoming an
180
+ empty session list. `accountsChanged` and `chainChanged` invalidate selection
181
+ even if namespace values are unchanged. The final pre-submission session check
182
+ runs after asynchronous digest/signature/network checks. Responses from another
183
+ SDK run cannot satisfy that check or restore submission authority.
184
+ Actual target-wallet acceptance of the serialization is an integration
185
+ requirement, not something inferred from these SDK APIs or a rejected request.
186
+
187
+ ## Funding formats in Sui 2.17.0
188
+
189
+ The pinned Transaction builder first resolves CoinWithBalance intents. With
190
+ SuiGrpcClient, the SDK's gRPC resolver then asks the node to resolve transaction
191
+ objects, gas payment, and expiration. The common client resolver is a separate
192
+ SDK path; testing it alone does not establish the runtime's gRPC behavior.
193
+
194
+ The source of truth for address-balance withdrawal and gas reservation formats
195
+ is Sui mainnet-v1.72.5 `sui-types/src/coin_reservation.rs` and
196
+ `transaction.rs`, together with the installed Sui 2.17.0 source. Its
197
+ `utils/coin-reservation.ts` helper is not publicly exported. The local read-only
198
+ funding verifier uses the SDK's public BCS, base58 and dynamic-field primitives
199
+ for the documented reservation format; it does not replace SDK coin selection
200
+ or import private package paths. Reservation epochs cover N and N+1.
201
+
202
+ Address-balance gas uses an empty payment array with ValidDuring replay
203
+ protection. A reservation reference can also fund a gas coin together with
204
+ actual coin objects. Source reads and checks-enabled review simulation remain
205
+ required; protocol feature availability alone does not prove wallet acceptance
206
+ or execution success.
@@ -0,0 +1,396 @@
1
+ # Signable Adapter and PTB Visualization Contract
2
+
3
+ This document defines the contract boundary for wallet-review adapters.
4
+ It is a product and implementation contract, not a current feature announcement.
5
+
6
+ The backend builds local account-bound DeepBook transaction material and
7
+ binds its Sui digest to verified review evidence. Only explicit user selection
8
+ and wallet approval allow the backend WalletConnect request. Returned bytes and
9
+ signer must match the admission before submission. No model or card receives
10
+ transaction bytes or signatures.
11
+
12
+ The source-level schema for this contract lives in
13
+ `src/core/action/signableAdapterContract.ts`.
14
+
15
+ ## Current Status
16
+
17
+ The contract schema is implemented in TypeScript and Zod, and the runtime
18
+ DeepBook account-bound swap reviews emit it. When an account-bound review
19
+ completes every evidence stage (local unsigned transaction material, internal
20
+ digest commitment, object ownership, quote/policy provenance, human-readable
21
+ review facts, and review-time simulation), the review layer assembles those
22
+ private artifacts into a schema-validated `TransactionReviewData` and
23
+ records it on the public review state as `transactionReviewData` on a
24
+ `ready_for_wallet_review` status. If any required evidence is
25
+ missing or fails contract validation, no contract is emitted and the review
26
+ stays blocked with `blockedReason: "wallet_review_contract_emit_missing"`.
27
+
28
+ If that stored failure's private evidence later becomes invalid, current state
29
+ retains the failure reason and stage provenance with `evidenceValidity:
30
+ "invalidated"` and removes the material-derived public summaries. Fresh
31
+ computation still validates every required summary; invalidation does not permit
32
+ a ready contract or wallet admission. Earlier recorded snapshots remain history.
33
+
34
+ `reviewedTransactionDigest` is a hash only. Private bytes travel directly from
35
+ the backend to the wallet through WalletConnect after atomic admission; there
36
+ is no browser handoff endpoint. The adapter contract itself never signs or
37
+ executes. The platform owns request authority and verified chain outcomes.
38
+
39
+ ## Final Acceptance Gate
40
+
41
+ This contract defines the data checks required before wallet admission; it does
42
+ not authorize a signature request. The current backend WalletConnect workflow
43
+ requires an explicit permitted Review card action and approval in the wallet.
44
+ The term signable adapter identifies this transaction-review contract, not a
45
+ claim that every displayed proposal is eligible for signing.
46
+
47
+ The gate binds three views of the action to one transaction commitment, so a
48
+ user cannot sign something different from what they reviewed:
49
+
50
+ - The commitment is a digest (hash) of the exact serialized transaction bytes
51
+ that will be signed, represented as the Sui transaction digest. The commitment
52
+ is a hash only; raw transaction bytes remain a prohibited output and must never
53
+ appear in MCP or review responses.
54
+ - `humanReadableReview` must be derived from the transaction identified by that
55
+ commitment.
56
+ - The review-time `simulation` must have been run against the transaction with
57
+ that same commitment.
58
+ - Any bytes handed to the wallet must hash to that same commitment.
59
+
60
+ The acceptance criterion is strict equality: review-commitment equals
61
+ simulation-commitment equals handoff-commitment. If any is missing or differs,
62
+ the contract is invalid and signing stays blocked.
63
+
64
+ ### Transaction byte lifecycle (closes the handoff loophole)
65
+
66
+ The signable bytes must have exactly one origin and one handoff path, so an
67
+ adapter cannot display a commitment while signing different bytes through a side
68
+ channel:
69
+
70
+ - Origin: the bytes are produced only inside Sui MCP's review layer (the
71
+ signable adapter), from material Sui MCP independently built or verified.
72
+ They are never accepted from an external MCP or AI-client proposal.
73
+ - Storage: the bytes live only in the local review-server session keyed by
74
+ `reviewSessionId`. They never appear in an MCP tool response or in the
75
+ review-API JSON an AI client reads; those surfaces carry the commitment hash
76
+ only.
77
+ - Transport: the only byte path is the private backend to the wallet through
78
+ its approved WalletConnect session. No browser signer or MCP response carries
79
+ bytes or signatures.
80
+ - Binding: before requesting a signature, recompute the stored bytes' digest
81
+ and require equality with both reviewed producers. Verify the returned bytes'
82
+ digest and selected account's signature again before one backend submission.
83
+ - Admission: one request per review session/revision, consumed atomically with
84
+ the card selection and public history. A different card cannot duplicate the
85
+ request. Recomputing while signature/submission callbacks or initial chain
86
+ observation remain unsettled is refused. Local timeout or stop does not prove
87
+ remote cancellation or callback cleanup.
88
+ - Results: request status and chain success/failure are separate. Unknown
89
+ outcomes retain the known digest and may be read again, never resubmitted.
90
+ A later explicit reviewed revision has a new attempt while prior facts remain.
91
+
92
+ DeepBook swap material is built with an explicit fee mode. When the account's
93
+ DEEP balance covers the protocol fee, the swap quotes and builds in DEEP fee
94
+ mode; otherwise it re-quotes through the protocol's input-fee dry run and
95
+ builds with an explicit zero-DEEP coin so the taker fee is paid from the
96
+ source coin at the protocol penalty. The selected fee mode is recorded as
97
+ review evidence and shown as a check. Before building, the producer verifies
98
+ the account holds the source amount plus the explicit gas budget and fails
99
+ closed with the exact required and held amounts.
100
+
101
+ This gate is enforced at the contract-schema layer. `transactionReviewDataSchema`
102
+ requires a `reviewedTransactionDigest` (the Sui transaction digest of the
103
+ transaction that will be signed, validated with the pinned SDK source of truth
104
+ `isValidTransactionDigest`; a digest only, never raw bytes) and binds
105
+ `humanReadableReview.transactionDigest` and `simulation.transactionDigest` to it
106
+ through a `superRefine` invariant (reusing the `requireEqual` cross-field helper)
107
+ that rejects any contract whose three commitments are missing, malformed, or
108
+ unequal (`src/core/action/signableAdapterContract.ts`,
109
+ `test/signableAdapterContract.test.ts`).
110
+
111
+ The private `prepareReviewedTransaction` session-store operation verifies stored
112
+ material and the reviewed digest. `WalletWorkflow` and its SQLite owner admit
113
+ the exact account/revision, verify wallet response bytes and signature, submit
114
+ once and record independently read receipt facts. Public output never gains
115
+ signing authority. Internal preparation is distinct from final user admission.
116
+
117
+ ## Adapter Contract
118
+
119
+ A wallet-review adapter that returns this contract must regenerate or
120
+ independently verify action material inside Sui MCP before any wallet
121
+ handoff exists. External MCP or AI-client proposals remain untrusted structured
122
+ input and cannot become transaction-building authority.
123
+
124
+ The adapter contract requires these fields:
125
+
126
+ - `inputProvenance`: where the request came from, when it was captured, and why
127
+ it remains untrusted until the local review layer regenerates and verifies it.
128
+ - `sourceReferences`: source metadata for pinned SDK registries, verified mainnet
129
+ onchain metadata, wallet reads, quote evidence, simulation, validated request
130
+ facts, or explicit user choices. A `sourceReferences` record is not itself a
131
+ value-bearing fact. It identifies where a typed evidence claim came from.
132
+ - `evidenceClaims`: typed value-bearing claims for every safety-critical fact
133
+ used by the payload. Each claim has a `factKind`, a `sourceEvidenceId` pointing
134
+ to `sourceReferences[].id`, and the value fields required for that fact. The
135
+ schema validates the claim against the safety-critical fact matrix and then
136
+ validates that payload fields match their referenced claim values.
137
+ - `rawQuantities`: raw integer strings plus normalized Sui coin type, verified
138
+ decimals, and unit source. `amountClaimId` must point to a
139
+ `raw_quantity_amount` claim whose role, raw amount, and normalized coin type
140
+ match the payload. Unit `unitClaimId` must point to a `unit_metadata` claim
141
+ whose decimals, normalized coin type, and metadata source match the payload.
142
+ Display amounts remain presentation-only.
143
+ - `gas`: review-time simulation evidence for gas quantities or a concrete
144
+ unresolved reason. `gasBudgetRaw` and `gasUsedRaw` must point to
145
+ `raw_quantity_amount` claims with `gas_budget` and `gas_used` roles, the Sui
146
+ gas coin type, and raw MIST units. An unresolved gas status must point to a
147
+ `gas_unresolved_status` claim. Gas object ownership must point to
148
+ `object_ownership` claims whose ownership status is `owned_by_account`.
149
+ `gasUsedRaw` is the nonnegative net simulation cost. If storage rebates exceed
150
+ costs, omit this optional unsigned quantity and its claim; do not clamp it to
151
+ zero. The verified gas budget remains available, and the review simulation
152
+ retains the exact cost/rebate components and signed balance changes.
153
+ - `expiry`: review-time expiry status. `current` and `expired` require
154
+ `checkedAt`, `expiresAt`, and `evidenceClaimId`; `current` requires
155
+ `expiresAt` after `checkedAt`, and `expired` requires `expiresAt` at or before
156
+ `checkedAt`. The referenced `expiry_status` claim must match the payload and
157
+ must reference a `sourceReferences` record with `checkedAt` and `expiresAt`.
158
+ `not_provided` and `not_applicable` must omit `expiresAt`, include
159
+ `evidenceClaimId` and `reason`, and reference an `expiry_status` claim backed
160
+ by `checkedAt` and `expiryStatus`.
161
+ - `slippageOrMinOut`: quote-linked max slippage and minimum-output policy when
162
+ quote evidence is used. `quoteEvidenceClaimId` must point to a `quote_min_out`
163
+ claim whose `quoteEvidenceId` and `minOutRaw` match the payload.
164
+ `policySource: "user_explicit"` requires a separate `policyEvidenceClaimId`
165
+ pointing to a `slippage_policy` claim backed by `user_explicit_choice` fields
166
+ including `maxSlippageBps` and `userSelection`.
167
+ `policySource: "adapter_policy_from_quote_evidence"` requires
168
+ `policyEvidenceClaimId` pointing to a `slippage_policy` claim backed by quote
169
+ evidence fields including `maxSlippageBps` and `minOutRaw`. If `minOutRaw` or
170
+ `maxSlippageBps` appears in the payload, it must have the matching typed claim;
171
+ stale or missing status does not make an unclaimed scalar safe to use.
172
+ `minOutRaw` must also match a `rawQuantities[]` entry with role
173
+ `minimum_output` so the raw integer has normalized coin type and verified
174
+ decimals.
175
+ - `objectOwnership`: account-bound object ownership or shared-object facts. Each
176
+ object must point to an `object_ownership` claim whose object id, owner account,
177
+ and ownership status match the payload.
178
+ - `simulation`: the public Sui gRPC `transactionExecutionService.simulateTransaction`
179
+ with validation checks enabled, identical returned transaction BCS and matching
180
+ effects digest. The required normalized evidence fields are `effects`,
181
+ `balanceChanges`, `objectTypes`, and `transaction`. The simulation payload must point to a `simulation_result`
182
+ claim whose provider, status, required fields, missing fields, and failure
183
+ reason match the payload.
184
+ - `humanReadableReview`: the fields a human must see before wallet
185
+ authorization, matching the review-model concepts already exposed for
186
+ non-signable proposal review.
187
+ - `outputBoundary`: the MCP and review UI exposure limit. Human-readable review,
188
+ PTB visualization artifacts, diagnostics, and status checks are allowed.
189
+ The required prohibited set is executable transaction material, serialized
190
+ transaction material, wallet signature requests, private-key material, wallet
191
+ authorization, signing data, signing readiness, and payment execution
192
+ readiness. Each contract must include the whole prohibited set.
193
+
194
+ ## Safety-Critical Fact Matrix
195
+
196
+ `SAFETY_CRITICAL_FACT_MATRIX` in `src/core/action/signableAdapterContract.ts`
197
+ is the contract's validation source of truth.
198
+
199
+ It defines the required source kind and source fields for these fact kinds:
200
+
201
+ - `raw_quantity_amount`, keyed by role: input, expected output, minimum output,
202
+ gas budget, gas used, fee, and balance delta;
203
+ - `unit_metadata`, keyed by metadata source;
204
+ - `gas_unresolved_status`;
205
+ - `expiry_status`, keyed by status;
206
+ - `quote_min_out`;
207
+ - `slippage_policy`, keyed by policy source;
208
+ - `object_ownership`;
209
+ - `simulation_result`.
210
+
211
+ Payload fields do not cite `sourceReferences` records directly as proof. They cite
212
+ typed evidence claims, and those claims cite `sourceReferences` records. The schema
213
+ rejects payload values that do not match their typed claims.
214
+
215
+ ## Consumer Invariant Matrix
216
+
217
+ `CONSUMER_INVARIANT_MATRIX` in
218
+ `src/core/action/signableAdapterContract.ts` defines extra requirements for
219
+ payload fields that consume typed claims. It is separate from
220
+ `SAFETY_CRITICAL_FACT_MATRIX`.
221
+
222
+ `SAFETY_CRITICAL_FACT_MATRIX` answers whether a typed claim has the required
223
+ source kind and source fields. `CONSUMER_INVARIANT_MATRIX` answers whether that
224
+ claim is valid for a specific payload use.
225
+
226
+ Current consumer invariants are:
227
+
228
+ - `gas.gasBudgetClaimId` must reference a `raw_quantity_amount` claim with role
229
+ `gas_budget`, matching raw amount, and Sui gas coin type. The raw unit is MIST.
230
+ - `gas.gasUsedClaimId` must reference a `raw_quantity_amount` claim with role
231
+ `gas_used`, matching raw amount, and Sui gas coin type. The raw unit is MIST.
232
+ - `gas.gasObjects[].ownershipClaimId` must reference an `object_ownership` claim
233
+ with matching object id, matching owner account, and
234
+ `ownership: "owned_by_account"`.
235
+
236
+ The current contract does not prove that a gas object is a `Coin<SUI>` object
237
+ type because the object-ownership claim does not carry object type evidence.
238
+ An adapter must not use object ownership alone as gas coin type evidence.
239
+
240
+ ## PTB Visualization Artifact
241
+
242
+ The PTB visualization contract is for explaining a locally generated
243
+ transaction shape before wallet authorization. It is not wallet handoff.
244
+
245
+ The artifact may contain:
246
+
247
+ - `generatedAt`;
248
+ - `source`, including adapter id, plan id when available, source kind, renderer
249
+ name, package name, and version;
250
+ - Mermaid `flowchart` text;
251
+ - diagnostics from the adapter, renderer, schema, or simulation;
252
+ - `unsupportedUse`, including transaction-building input, wallet authorization,
253
+ signing data, signing readiness, payment execution readiness, and route
254
+ recommendation;
255
+ - `executableMaterial.included: false`.
256
+
257
+ The artifact must not contain executable transaction material. Mermaid text and
258
+ diagnostic messages are screened for executable-material terms and long encoded
259
+ payloads.
260
+
261
+ ## PTB Renderer Status
262
+
263
+ The pinned renderer dependency is `@zktx.io/ptb-model@0.5.0`. The review layer
264
+ converts the stored local transaction material into a Mermaid `flowchart`
265
+ artifact with `rawTransactionToIR` and `transactionIRToMermaid`, only after the
266
+ stored bytes are recomputed to match the bound transaction material commitment;
267
+ a mismatch declines the artifact. The graph is decoded from the stored transaction bytes with no AI or model input in the rendering path, so it reflects the decoded transaction the wallet will receive, not an AI description of it. The artifact passes
268
+ `ptbVisualizationArtifactSchema` screening before exposure and accompanies the
269
+ emitted wallet review contract as `reviewState.ptbVisualization`. PTB
270
+ visualization stays visualization-only evidence: it is not a runtime
271
+ transaction builder, not wallet handoff, and not a signing-readiness surface.
272
+
273
+ The producer emits the Mermaid flowchart as two parallel streams. `mermaid.text`
274
+ keeps raw package addresses for audit and copy. `mermaid.namedText` is a second
275
+ relabeled stream produced by `applyContractNamesToMermaid`
276
+ (`src/core/action/ptbVisualizationProducer.ts`,
277
+ `src/core/action/contractNameRegistry.ts`): it labels registered packages
278
+ (`@deepbook/core`; the Sui framework `std`/`sui`/`sui_system`) and well-known
279
+ objects (`SuiSystemState`, `Clock`, `Random`, `DenyList`, `CoinRegistry`,
280
+ `AccumulatorRoot`) while keeping the raw addresses available. These names are a
281
+ display label, not a safety, ownership, or trust signal, and the on-chain Move
282
+ Registry name is not yet verified on chain.
283
+
284
+ ## Adapter Registration And Stage Vocabulary
285
+
286
+ Review adapters register through `ReviewAdapterDescriptor` entries in
287
+ `src/adapters/reviewAdapters.ts` (`buildSupportedReviewAdapterDescriptors`).
288
+ A descriptor supplies the adapter id, protocol, action kind, stage catalog id,
289
+ and the evidence computer; action-plan factories live in the adapter module
290
+ and are wired by the MCP layer. The platform keeps the
291
+ safety gates non-delegable: the typed evidence claim matrices, the commitment
292
+ equality gate, the adapter lifecycle validator registry
293
+ (`src/adapters/adapterLifecycleValidators.ts`), and the digest-gated byte
294
+ handoff all run outside adapter code. `src/core` contains no adapter imports;
295
+ a source-policy test enforces that boundary.
296
+
297
+ Stage vocabulary is a cross-adapter contract. Every stage catalog that reports
298
+ public review evidence must use these stage ids for these concepts, because the
299
+ core review-state schema binds public fields to them:
300
+
301
+ - `transaction_material_build_or_verify`: local unsigned material exists.
302
+ - `digest_commitment`: the Sui transaction digest is bound to the material.
303
+ - `object_ownership`: object ownership evidence is verified.
304
+ - `human_readable_review`: required before `reviewState.humanReadableReview`.
305
+ - `review_time_simulation`: required before `reviewState.simulation`.
306
+
307
+ Adapter acceptance gate: a new protocol enters as read-only tools or
308
+ non-signable proposal review first. A signable adapter is accepted only when it
309
+ produces every required evidence stage from independently built or verified
310
+ material, passes `transactionReviewDataSchema` without placeholder
311
+ values, and fails closed when any evidence is missing. Protocol names stay out
312
+ of public docs, runtime guidance, and MCP resources until a concrete
313
+ implementation or support decision exists.
314
+
315
+ ## Verification
316
+
317
+ Tests must keep this contract in place before any adapter can use it:
318
+
319
+ - schema tests for required provenance, source-of-truth, raw quantity, gas,
320
+ expiry, slippage or minimum output, object ownership, simulation, and
321
+ human-readable review fields;
322
+ - tests that reject duplicate `sourceReferences[].id` and `evidenceClaims[].id`
323
+ values;
324
+ - tests that reject every payload claim reference that does not resolve to a
325
+ typed `evidenceClaims[].id`;
326
+ - tests that reject every `evidenceClaims[].sourceEvidenceId` that does not
327
+ resolve to a `sourceReferences[].id`;
328
+ - tests that reject safety-critical claims whose source references resolve to the
329
+ wrong source kind or to records missing the required fields for that claim;
330
+ - tests that reject payload values whose raw amounts, decimals, gas quantities,
331
+ expiry values, minimum output, slippage policy, object ownership, or simulation
332
+ status do not match their typed evidence claims;
333
+ - tests that reject metadata-only records as raw amount evidence and reject
334
+ user-explicit slippage policy claims without explicit user-choice evidence;
335
+ - tests that reject raw signable quantity assets without normalized Sui coin
336
+ types;
337
+ - tests that reject min-out or slippage scalar fields when they do not have typed
338
+ evidence claims;
339
+ - tests that reject `minOutRaw` when it does not match a `rawQuantities[]` entry
340
+ with role `minimum_output`;
341
+ - tests that require `gasBudgetRaw` and `gasUsedRaw` to use
342
+ `raw_quantity_amount` claims with gas roles, the Sui gas coin type, and raw
343
+ MIST units, or require unresolved gas status to use a `gas_unresolved_status`
344
+ claim;
345
+ - tests that reject gas object references backed by object-ownership claims whose
346
+ ownership status is not `owned_by_account`;
347
+ - tests that require every mandatory prohibited output boundary and every
348
+ mandatory PTB unsupported-use boundary;
349
+ - tests that reject `current` or `expired` expiry status without timestamp
350
+ evidence, source evidence, matching source fields, and the required
351
+ `checkedAt`/`expiresAt` time relationship;
352
+ - tests that reject `not_provided` or `not_applicable` expiry status when it
353
+ includes an `expiresAt` timestamp or omits the reason and source evidence for
354
+ why timestamp evidence is unavailable;
355
+ - tests that require failed or unavailable simulation evidence to include a
356
+ concrete `failureReason`;
357
+ - tests that reject display amounts, exponent notation, or floating-point values
358
+ as raw quantities;
359
+ - tests that reject PTB visualization artifacts containing executable-material
360
+ terms or long encoded payloads;
361
+ - MCP/review output tests using the shared forbidden-field-name policy;
362
+ - documentation tests that keep PTB visualization described as visualization
363
+ only, not transaction material, signing readiness, or payment execution
364
+ readiness.
365
+
366
+ ## Transaction funding and ownership
367
+
368
+ The supported swap adapters retain the SDK's coin-object and address-balance
369
+ selection. The private ownership evidence verifies the stored transaction's
370
+ sender, gas payer, real object references, address withdrawals, and gas funding
371
+ against the reviewed account and verified mainnet source. The same description
372
+ must match the checks-enabled simulation and the material rechecked for admission.
373
+
374
+ An empty gas payment array means address-balance gas; it is not missing gas
375
+ evidence. It requires a mainnet-bound ValidDuring epoch window and address SUI
376
+ covering both explicit SUI withdrawals and the gas budget. A gas reservation
377
+ reference is an address-balance reservation, not a Coin<SUI> object. Its account,
378
+ asset, chain, amount and epoch are verified; any real gas coins alongside it
379
+ retain their ownership/type checks. Explicit address withdrawals and reservations
380
+ are summed per coin type without counting the gas budget twice. Observed balances
381
+ are review-time facts, not locked funds or execution guarantees.
382
+
383
+ Only real gas coins produce `gas.gasObjects` and object-ownership claims. The
384
+ public optional field remains absent when no such objects are used. Private
385
+ funding evidence is required in either case; omitting all funding checks does not
386
+ produce a valid review. The existing human review evidence explains the funding
387
+ form without publishing private artifacts or creating signing authority.
388
+
389
+ Different gas owners, sponsor withdrawals, unsupported reservation formats, and
390
+ unverified funding remain blocked. Supported adapters still require the same quote,
391
+ amount, ownership, human review, simulation, wallet approval, and digest checks.
392
+
393
+ New review evidence names `client.transactionExecutionService.simulateTransaction`
394
+ as its provider. The previous `client.core.simulateTransaction` provider remains
395
+ parseable in stored public history; it is not a fallback for new reviews. Returned
396
+ BCS is compared privately and is never added to evidence, cards, backups or logs.