@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,389 @@
1
+ import { REVIEW_PREPARATION_STATUSES } from "../action/types.js";
2
+ import { TRANSACTION_REQUEST_STATUSES } from "../session/transactionRequest.js";
3
+ import { actionPlanSchema } from "../action/schemas.js";
4
+ import { assertNoForbiddenMcpFields } from "../action/forbiddenFields.js";
5
+ import { ActivityStoreReadError, EXTERNAL_ACTIVITY_SCAN_MAX_LIMIT, REVIEW_ACTIVITY_LIST_DEFAULT_LIMIT, REVIEW_ACTIVITY_LIST_MAX_LIMIT, REVIEW_ACTIVITY_LOW_SAMPLE_THRESHOLD } from "./activityStore.js";
6
+ import { EXTERNAL_ACTIVITY_TRANSACTION_DETAIL_JSON_MAX_BYTES, externalActivityTransactionDetailJsonByteLength, externalActivityTransactionDetailSchema, externalActivityTransactionDetailsReferenceOnlyAccount } from "./transactionActivityDetails.js";
7
+ import { ActivityStoreError } from "./sqliteActivityStoreTypes.js";
8
+ export const INTERNAL_SESSION_STATUSES = REVIEW_PREPARATION_STATUSES;
9
+ export const REVIEW_STATE_STATUSES = [
10
+ "ready_for_wallet_review",
11
+ "blocked",
12
+ "refresh_required"
13
+ ];
14
+ export const REVIEW_TRANSITION_EVENTS = [
15
+ "created",
16
+ "opened",
17
+ "wallet_connected",
18
+ "state_computed",
19
+ "request_admitted", "request_status_changed", "signature_verified", "chain_result_recorded", "review_update_failed", "review_invalidated",
20
+ "expired"
21
+ ];
22
+ export const EXTERNAL_ACTIVITY_RELATIONSHIPS = ["affected", "sent"];
23
+ export const EXTERNAL_ACTIVITY_STATUSES = ["success", "failure", "unknown"];
24
+ const EXTERNAL_ACTIVITY_INCOMPLETE_REASONS = [
25
+ "limit_reached",
26
+ "ordering_unverified",
27
+ "cursor_invalid",
28
+ "provider_error"
29
+ ];
30
+ export function parseIsoTimestamp(value, field) {
31
+ const parsed = new Date(value);
32
+ if (Number.isNaN(parsed.getTime()) || parsed.toISOString() !== value) {
33
+ throw new ActivityStoreReadError("input_invalid", `${field} must be an ISO 8601 UTC timestamp`, {
34
+ field
35
+ });
36
+ }
37
+ return value;
38
+ }
39
+ export function parseOptionalIsoTimestamp(value, field) {
40
+ if (value === undefined) {
41
+ return undefined;
42
+ }
43
+ return parseIsoTimestamp(value, field);
44
+ }
45
+ export function assertDateRange(from, to) {
46
+ if (from && to && from > to) {
47
+ throw new ActivityStoreReadError("input_invalid", "from must be before or equal to to", {
48
+ from,
49
+ to
50
+ });
51
+ }
52
+ }
53
+ export function normalizeListLimit(limit) {
54
+ if (limit === undefined) {
55
+ return REVIEW_ACTIVITY_LIST_DEFAULT_LIMIT;
56
+ }
57
+ if (!Number.isInteger(limit) || limit < 1 || limit > REVIEW_ACTIVITY_LIST_MAX_LIMIT) {
58
+ throw new ActivityStoreReadError("input_invalid", "limit must be an integer from 1 to 100", {
59
+ limit,
60
+ min: 1,
61
+ max: REVIEW_ACTIVITY_LIST_MAX_LIMIT
62
+ });
63
+ }
64
+ return limit;
65
+ }
66
+ export function normalizeExternalActivityLimit(limit) {
67
+ if (limit === undefined) {
68
+ return EXTERNAL_ACTIVITY_SCAN_MAX_LIMIT;
69
+ }
70
+ if (!Number.isInteger(limit) || limit < 1 || limit > EXTERNAL_ACTIVITY_SCAN_MAX_LIMIT) {
71
+ throw new ActivityStoreReadError("input_invalid", "limit must be an integer from 1 to 100", {
72
+ limit,
73
+ min: 1,
74
+ max: EXTERNAL_ACTIVITY_SCAN_MAX_LIMIT
75
+ });
76
+ }
77
+ return limit;
78
+ }
79
+ export function reviewSessionWhere(accountId, from, to, status) {
80
+ const conditions = ["rs.account_id = ?"];
81
+ const params = [accountId];
82
+ if (from) {
83
+ conditions.push("rs.created_at >= ?");
84
+ params.push(from);
85
+ }
86
+ if (to) {
87
+ conditions.push("rs.created_at <= ?");
88
+ params.push(to);
89
+ }
90
+ if (status) {
91
+ conditions.push("rs.current_status = ?");
92
+ params.push(status);
93
+ }
94
+ return {
95
+ whereSql: `WHERE ${conditions.join(" AND ")}`,
96
+ params
97
+ };
98
+ }
99
+ export function reviewActivityRowFromStorage(row, request) {
100
+ return {
101
+ reviewSessionId: asString(row.review_session_id),
102
+ planId: asString(row.plan_id),
103
+ actionKind: asString(row.action_kind),
104
+ adapterId: asString(row.adapter_id),
105
+ protocol: asString(row.protocol),
106
+ reviewStatus: asInternalSessionStatus(row.current_status),
107
+ account: asString(row.account),
108
+ createdAt: asString(row.created_at),
109
+ updatedAt: asString(row.updated_at),
110
+ ...(request ? { currentAttemptId: request.attemptId, requestStatus: request.requestStatus, reviewRevision: request.reviewRevision,
111
+ transactionDigest: request.transactionDigest, ...(request.execution ? { executionStatus: request.execution.status } : {}) } : {}),
112
+ snapshotCount: row.snapshot_count,
113
+ transitionCount: row.transition_count
114
+ };
115
+ }
116
+ export function reviewActivityListResult(scope, from, to, activities, truncated, recordCount) {
117
+ return {
118
+ dataScope: dataScope(scope.account, from, to, recordCount),
119
+ accountSource: scope.accountSource,
120
+ lowSampleWarning: recordCount < REVIEW_ACTIVITY_LOW_SAMPLE_THRESHOLD,
121
+ lowSampleThreshold: REVIEW_ACTIVITY_LOW_SAMPLE_THRESHOLD,
122
+ truncated: {
123
+ activities: truncated,
124
+ snapshots: false,
125
+ transitions: false
126
+ },
127
+ activities
128
+ };
129
+ }
130
+ export function reviewFunnelResult(scope, from, to, summary, recordCount) {
131
+ return {
132
+ dataScope: dataScope(scope.account, from, to, recordCount),
133
+ accountSource: scope.accountSource,
134
+ lowSampleWarning: recordCount < REVIEW_ACTIVITY_LOW_SAMPLE_THRESHOLD,
135
+ lowSampleThreshold: REVIEW_ACTIVITY_LOW_SAMPLE_THRESHOLD,
136
+ truncated: {
137
+ activities: false,
138
+ snapshots: false,
139
+ transitions: false
140
+ },
141
+ summary
142
+ };
143
+ }
144
+ function dataScope(account, from, to, recordCount) {
145
+ const scope = {
146
+ account,
147
+ recordCount
148
+ };
149
+ if (from !== undefined) {
150
+ scope.from = from;
151
+ }
152
+ if (to !== undefined) {
153
+ scope.to = to;
154
+ }
155
+ return scope;
156
+ }
157
+ export function externalActivityScanFromRow(row) {
158
+ return {
159
+ scanId: asString(row.scan_id),
160
+ kind: asExternalActivityScanKind(row.kind),
161
+ accountId: row.account_id,
162
+ account: asString(row.account),
163
+ relationship: asExternalActivityRelationship(row.relationship),
164
+ inputDigest: row.input_digest === null ? undefined : asString(row.input_digest),
165
+ fromCheckpoint: row.from_checkpoint === null ? undefined : asString(row.from_checkpoint),
166
+ toCheckpoint: row.to_checkpoint === null ? undefined : asString(row.to_checkpoint),
167
+ fromTimestamp: row.from_timestamp === null ? undefined : asString(row.from_timestamp),
168
+ toTimestamp: row.to_timestamp === null ? undefined : asString(row.to_timestamp),
169
+ limit: row.limit_count,
170
+ requestCursor: row.request_cursor === null ? undefined : asString(row.request_cursor),
171
+ responseCursor: row.response_cursor === null ? undefined : asString(row.response_cursor),
172
+ endpointHost: asString(row.endpoint_host),
173
+ chainIdentifier: asString(row.chain_identifier),
174
+ fetchedAt: asString(row.fetched_at),
175
+ storedCount: row.stored_count,
176
+ skippedCount: row.skipped_count,
177
+ hasMore: row.has_more === 1,
178
+ windowComplete: row.window_complete === null ? null : row.window_complete === 1,
179
+ incompleteReason: row.incomplete_reason === null
180
+ ? undefined
181
+ : asExternalActivityIncompleteReason(row.incomplete_reason)
182
+ };
183
+ }
184
+ export function externalActivityTransactionFromRow(row) {
185
+ return {
186
+ accountId: row.account_id,
187
+ account: asString(row.account),
188
+ digest: asString(row.digest),
189
+ relationship: asExternalActivityRelationship(row.relationship),
190
+ checkpoint: row.checkpoint === null ? undefined : asString(row.checkpoint),
191
+ timestamp: row.timestamp === null ? undefined : asString(row.timestamp),
192
+ status: asExternalActivityStatus(row.status),
193
+ knownSenderAccountId: row.known_sender_account_id === null ? undefined : row.known_sender_account_id,
194
+ firstScanId: asString(row.first_scan_id),
195
+ lastScanId: asString(row.last_scan_id),
196
+ firstFetchedAt: asString(row.first_fetched_at),
197
+ lastFetchedAt: asString(row.last_fetched_at),
198
+ lastScanIncompleteReason: row.last_scan_incomplete_reason === null
199
+ ? undefined
200
+ : asExternalActivityIncompleteReason(row.last_scan_incomplete_reason),
201
+ details: row.detail_json === null
202
+ ? undefined
203
+ : parseEvidenceJson(row.detail_json, asString(row.digest), "external_activity_detail", externalActivityTransactionDetailSchema)
204
+ };
205
+ }
206
+ export function externalActivitySummaryResult(scope, from, to, transactions, truncated, stats) {
207
+ const summary = {
208
+ transactionCount: stats.transactionCount,
209
+ statusCounts: stats.statusCounts,
210
+ relationshipCounts: stats.relationshipCounts
211
+ };
212
+ if (stats.earliestTimestamp !== undefined) {
213
+ summary.earliestTimestamp = stats.earliestTimestamp;
214
+ }
215
+ if (stats.latestTimestamp !== undefined) {
216
+ summary.latestTimestamp = stats.latestTimestamp;
217
+ }
218
+ return {
219
+ dataScope: dataScope(scope.account, from, to, stats.transactionCount),
220
+ accountSource: scope.accountSource,
221
+ lowSampleWarning: stats.transactionCount < REVIEW_ACTIVITY_LOW_SAMPLE_THRESHOLD,
222
+ lowSampleThreshold: REVIEW_ACTIVITY_LOW_SAMPLE_THRESHOLD,
223
+ truncated,
224
+ summary,
225
+ transactions
226
+ };
227
+ }
228
+ export function emptyExternalActivitySummaryStats() {
229
+ return {
230
+ transactionCount: 0,
231
+ statusCounts: Object.fromEntries(EXTERNAL_ACTIVITY_STATUSES.map((status) => [status, 0])),
232
+ relationshipCounts: Object.fromEntries(EXTERNAL_ACTIVITY_RELATIONSHIPS.map((relationship) => [relationship, 0]))
233
+ };
234
+ }
235
+ export function emptyReviewFunnelSummary() {
236
+ return { total: 0, opened: 0, walletConnected: 0, stateComputed: 0,
237
+ reviewStatusCounts: countMap(INTERNAL_SESSION_STATUSES, []),
238
+ requestStatusCounts: TRANSACTION_REQUEST_STATUSES.map((requestStatus) => ({ requestStatus, count: 0 })), executionStatusCounts: { success: 0, failure: 0 },
239
+ withoutRequest: 0, withoutExecutionResult: 0,
240
+ everReachedReviewStateCounts: countMap(REVIEW_STATE_STATUSES, []), everAwaitedChainResult: 0,
241
+ expiredWithoutExecutionResult: 0, avgCreatedToSignatureVerifiedSeconds: null, avgOpenedToSignatureVerifiedSeconds: null };
242
+ }
243
+ export function countMap(keys, rows) {
244
+ const result = Object.fromEntries(keys.map((key) => [key, 0]));
245
+ for (const row of rows) {
246
+ if (keys.includes(row.key)) {
247
+ result[row.key] = row.count;
248
+ }
249
+ }
250
+ return result;
251
+ }
252
+ export function nullableSeconds(value) {
253
+ return value === null ? null : Math.round(value * 1000) / 1000;
254
+ }
255
+ export function parseEvidenceJson(value, reviewSessionId, evidenceField, schema) {
256
+ if (value === null) {
257
+ throw new ActivityStoreReadError("internal_error", "Malformed activity JSON evidence", {
258
+ reviewSessionId,
259
+ evidenceField
260
+ });
261
+ }
262
+ let parsed;
263
+ try {
264
+ parsed = JSON.parse(value);
265
+ }
266
+ catch {
267
+ throw new ActivityStoreReadError("internal_error", "Malformed activity JSON evidence", {
268
+ reviewSessionId,
269
+ evidenceField
270
+ });
271
+ }
272
+ if (schema !== undefined) {
273
+ const result = schema.safeParse(parsed);
274
+ if (!result.success) {
275
+ throw new ActivityStoreReadError("internal_error", "Malformed activity JSON evidence", {
276
+ reviewSessionId,
277
+ evidenceField
278
+ });
279
+ }
280
+ return result.data;
281
+ }
282
+ return parsed;
283
+ }
284
+ export function serializeJson(value) {
285
+ assertNoForbiddenMcpFields(value);
286
+ return JSON.stringify(value);
287
+ }
288
+ export function serializeExternalActivityTransactionDetail(details, account) {
289
+ const parsed = externalActivityTransactionDetailSchema.safeParse(details);
290
+ if (!parsed.success || !externalActivityTransactionDetailsReferenceOnlyAccount(parsed.data, account)) {
291
+ throw new ActivityStoreReadError("input_invalid", "Invalid external activity transaction detail", {
292
+ reason: "invalid_external_activity_detail_json"
293
+ });
294
+ }
295
+ const json = serializeJson(parsed.data);
296
+ if (externalActivityTransactionDetailJsonByteLength(json) > EXTERNAL_ACTIVITY_TRANSACTION_DETAIL_JSON_MAX_BYTES) {
297
+ throw new ActivityStoreReadError("input_invalid", "External activity transaction detail JSON is too large", {
298
+ reason: "external_activity_detail_too_large",
299
+ maxBytes: EXTERNAL_ACTIVITY_TRANSACTION_DETAIL_JSON_MAX_BYTES
300
+ });
301
+ }
302
+ return json;
303
+ }
304
+ export function serializeOptionalJson(value) {
305
+ if (value === undefined) {
306
+ return null;
307
+ }
308
+ return serializeJson(value);
309
+ }
310
+ export function parseActionPlanEvidence(plan) {
311
+ const parsed = actionPlanSchema.safeParse(plan);
312
+ if (!parsed.success) {
313
+ throw new ActivityStoreError("Invalid review session action plan evidence");
314
+ }
315
+ return parsed.data;
316
+ }
317
+ export function extractRequestedIntent(plan) {
318
+ // Adapter convention: full plan_json stays canonical, while requestedIntent
319
+ // is materialized only to make activity queries avoid nested JSON paths.
320
+ return plan.adapterData.requestedIntent;
321
+ }
322
+ export function reasonForReviewState(state) {
323
+ if ("blockedReason" in state) {
324
+ return state.blockedReason;
325
+ }
326
+ if ("refreshReason" in state) {
327
+ return state.refreshReason;
328
+ }
329
+ return undefined;
330
+ }
331
+ export function asString(value) {
332
+ if (typeof value !== "string") {
333
+ throw new ActivityStoreError("Unexpected SQLite value type");
334
+ }
335
+ return value;
336
+ }
337
+ export function coinMetadataCacheRecordFromRow(row) {
338
+ return {
339
+ coinType: asString(row.coin_type),
340
+ chainIdentifier: asString(row.chain_identifier),
341
+ decimals: row.decimals,
342
+ symbol: asString(row.symbol),
343
+ name: asString(row.name),
344
+ fetchedAt: asString(row.fetched_at),
345
+ expiresAt: asString(row.expires_at)
346
+ };
347
+ }
348
+ export function asInternalSessionStatus(value) {
349
+ if (typeof value === "string" && INTERNAL_SESSION_STATUSES.includes(value)) {
350
+ return value;
351
+ }
352
+ throw new ActivityStoreError("Unexpected review status");
353
+ }
354
+ export function asReviewTransitionEvent(value) {
355
+ if (typeof value === "string" && REVIEW_TRANSITION_EVENTS.includes(value)) {
356
+ return value;
357
+ }
358
+ throw new ActivityStoreError("Unexpected review transition event");
359
+ }
360
+ export function asAccountSource(value) {
361
+ if (value === "wallet_connection" || value === "review_execution") {
362
+ return value;
363
+ }
364
+ throw new ActivityStoreError("Unexpected account source");
365
+ }
366
+ function asExternalActivityScanKind(value) {
367
+ if (value === "digest_lookup" || value === "account_scan" || value === "function_scan") {
368
+ return value;
369
+ }
370
+ throw new ActivityStoreError("Unexpected external activity scan kind");
371
+ }
372
+ function asExternalActivityRelationship(value) {
373
+ if (typeof value === "string" && EXTERNAL_ACTIVITY_RELATIONSHIPS.includes(value)) {
374
+ return value;
375
+ }
376
+ throw new ActivityStoreError("Unexpected external activity relationship");
377
+ }
378
+ function asExternalActivityStatus(value) {
379
+ if (typeof value === "string" && EXTERNAL_ACTIVITY_STATUSES.includes(value)) {
380
+ return value;
381
+ }
382
+ throw new ActivityStoreError("Unexpected external activity status");
383
+ }
384
+ function asExternalActivityIncompleteReason(value) {
385
+ if (typeof value === "string" && EXTERNAL_ACTIVITY_INCOMPLETE_REASONS.includes(value)) {
386
+ return value;
387
+ }
388
+ throw new ActivityStoreError("Unexpected external activity incomplete reason");
389
+ }