@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,391 @@
1
+ import { createRuntimeReviewDependencies } from "./reviewDependencies.js";
2
+ import { computeSmokeReview, SmokeReviewConfigError } from "./smokeReview.js";
3
+ import { parseSuiAddress } from "../core/suiAddress.js";
4
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
5
+ import { randomInt } from "node:crypto";
6
+ import { tmpdir } from "node:os";
7
+ import { join } from "node:path";
8
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9
+ import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
10
+ import { validateSupportedAdapterLifecycle } from "../adapters/adapterLifecycleValidators.js";
11
+ import { SqliteActivityStore } from "../core/activity/sqliteActivityStore.js";
12
+ import { TransactionActivityService } from "../core/activity/transactionActivityService.js";
13
+ import { createSuiReadService } from "../core/read/readService.js";
14
+ import { DeepbookOfficialIndexerSource } from "../core/read/deepbookOfficialIndexerSource.js";
15
+ import { LocalSessionStore } from "../core/session/sessionStore.js";
16
+ import { createMcpServer } from "../mcp/server.js";
17
+ import { TOOL_NAMES } from "../mcp/toolNames.js";
18
+ import { DEFAULT_SUI_GRAPHQL_URL, DEFAULT_SUI_GRPC_URL, composeRuntimeConfig, loadBootConfig } from "./config.js";
19
+ import { RuntimeLocalSettingsService } from "./localSettingsService.js";
20
+ import { createStderrLogger } from "./logger.js";
21
+ import { SmokeResponseShapeError, assertSmokeOkStatus, summarizeActivitySmokePayload } from "./smokeMainnetReadAssertions.js";
22
+ import { SuiEndpointError, verifyMainnetGraphqlEndpoint, verifyMainnetGrpcEndpoint } from "./suiEndpoint.js";
23
+ import { GraphqlSuiTransactionActivitySource } from "./suiTransactionGraphqlSource.js";
24
+ const startedAt = new Date();
25
+ const smokeFunctionTarget = process.env.SMOKE_FUNCTION_TARGET;
26
+ const plannedTools = [
27
+ TOOL_NAMES.readSummarizeWalletAssets,
28
+ TOOL_NAMES.readInspectDeepbookOrderbook,
29
+ TOOL_NAMES.readQuoteDeepbookAction,
30
+ TOOL_NAMES.readScanSuiAccountActivity,
31
+ TOOL_NAMES.readSummarizeSuiActivityScan,
32
+ ...(smokeFunctionTarget
33
+ ? [
34
+ TOOL_NAMES.readScanSuiFunctionActivity,
35
+ TOOL_NAMES.readSummarizeSuiFunctionActivityScan
36
+ ]
37
+ : [])
38
+ ];
39
+ const attemptedTools = [];
40
+ const completedTools = [];
41
+ const activitySmoke = {};
42
+ const functionActivitySmoke = smokeFunctionTarget
43
+ ? {
44
+ tools: [
45
+ TOOL_NAMES.readScanSuiFunctionActivity,
46
+ TOOL_NAMES.readSummarizeSuiFunctionActivityScan
47
+ ]
48
+ }
49
+ : {
50
+ status: "not_run",
51
+ tools: [
52
+ TOOL_NAMES.readScanSuiFunctionActivity,
53
+ TOOL_NAMES.readSummarizeSuiFunctionActivityScan
54
+ ],
55
+ notRunReason: "missing_env"
56
+ };
57
+ const ACTIVITY_SMOKE_LIMIT = 5;
58
+ class SmokeMainnetError extends Error {
59
+ category;
60
+ constructor(category, message) {
61
+ super(message);
62
+ this.category = category;
63
+ }
64
+ }
65
+ async function main() {
66
+ const logger = createStderrLogger("smoke-mainnet");
67
+ const bootConfig = loadSmokeBootConfig();
68
+ const smokeAddress = parseSuiAddress(requiredEnv("SMOKE_SUI_ADDRESS")) ?? fail("config_error", "SMOKE_SUI_ADDRESS must be a Sui address.");
69
+ const poolKey = requiredEnv("SMOKE_DEEPBOOK_POOL_KEY");
70
+ const quoteAmount = requiredEnv("SMOKE_QUOTE_AMOUNT");
71
+ const inspectDigest = process.env.SMOKE_INSPECT_DIGEST;
72
+ const inspectRandomLatest = truthyEnv("SMOKE_INSPECT_RANDOM_LATEST");
73
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
74
+ const client = new Client({ name: "sui-mcp-smoke", version: "0.0.0" });
75
+ let smokeDbDir;
76
+ let activityStore;
77
+ let server;
78
+ try {
79
+ smokeDbDir = mkdtempSync(join(tmpdir(), "sui-mcp-smoke-db-"));
80
+ activityStore = new SqliteActivityStore({
81
+ databasePath: join(smokeDbDir, "sui-mcp.sqlite"),
82
+ validateAdapterLifecycle: validateSupportedAdapterLifecycle
83
+ });
84
+ const preferencesRepository = activityStore.createPreferencesRepository();
85
+ await preferencesRepository.ensureDefaultLocalSettings({
86
+ suiGrpcUrl: DEFAULT_SUI_GRPC_URL,
87
+ suiGraphqlUrl: DEFAULT_SUI_GRAPHQL_URL
88
+ });
89
+ const storedSuiGrpcUrl = await preferencesRepository.getSuiGrpcUrl();
90
+ const storedSuiGraphqlUrl = await preferencesRepository.getSuiGraphqlUrl();
91
+ const config = composeRuntimeConfig({
92
+ bootConfig,
93
+ env: process.env,
94
+ storedSuiGrpcUrl: storedSuiGrpcUrl?.value,
95
+ storedSuiGraphqlUrl: storedSuiGraphqlUrl?.value,
96
+ defaultSuiGrpcUrl: DEFAULT_SUI_GRPC_URL,
97
+ defaultSuiGraphqlUrl: DEFAULT_SUI_GRAPHQL_URL
98
+ });
99
+ const { client: suiClient, chainIdentifier } = await verifyMainnetGrpcEndpoint({
100
+ url: config.grpcUrl,
101
+ expectedChainIdentifier: config.expectedChainIdentifier
102
+ });
103
+ const localSettings = new RuntimeLocalSettingsService({
104
+ preferencesRepository,
105
+ env: process.env,
106
+ defaultSuiGrpcUrl: DEFAULT_SUI_GRPC_URL,
107
+ defaultSuiGraphqlUrl: DEFAULT_SUI_GRAPHQL_URL,
108
+ bootSuiGrpcUrl: config.suiGrpcUrl,
109
+ bootSuiGraphqlUrl: config.suiGraphqlUrl
110
+ });
111
+ const readService = createSuiReadService({
112
+ client: suiClient,
113
+ network: config.network,
114
+ chainIdentifier,
115
+ coinMetadataCache: activityStore.createCoinMetadataCache(),
116
+ deepbookOfficialIndexerSource: new DeepbookOfficialIndexerSource()
117
+ });
118
+ const transactionMaterialStore = activityStore.createTransactionMaterialStore();
119
+ const sessions = new LocalSessionStore({
120
+ activityStore,
121
+ logger,
122
+ validateAdapterLifecycle: validateSupportedAdapterLifecycle,
123
+ sessions: activityStore.createSessionRecordStore(),
124
+ artifacts: activityStore.createPrivateReviewArtifactStore(),
125
+ settingsStore: activityStore.createSettingsRecordStore()
126
+ });
127
+ const reviewDependencies = createRuntimeReviewDependencies({ client: suiClient, chainIdentifier,
128
+ expectedChainIdentifier: config.expectedChainIdentifier, materialStore: transactionMaterialStore, readService });
129
+ // Utility-only read context in this script's temporary DB. This does not
130
+ // create a live wallet session or prove address ownership.
131
+ await activityStore.setActiveAccount(smokeAddress, "wallet_connection", new Date(), { name: "Explicit smoke read fixture" });
132
+ server = createMcpServer({
133
+ sessions,
134
+ activityStore,
135
+ localSettings,
136
+ readService,
137
+ transactionActivityService: new TransactionActivityService({
138
+ activityStore,
139
+ source: new GraphqlSuiTransactionActivitySource({
140
+ url: config.graphqlUrl,
141
+ expectedChainIdentifier: config.expectedChainIdentifier
142
+ })
143
+ }),
144
+ logger
145
+ });
146
+ await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
147
+ const accountBoundSwapReview = await computeSmokeReview({ env: process.env, account: smokeAddress, sessions, computation: reviewDependencies });
148
+ if (accountBoundSwapReview.status === "ok")
149
+ markCompleted("account_bound_swap_review");
150
+ const wallet = await callSmokeTool(client, TOOL_NAMES.readSummarizeWalletAssets, {});
151
+ const orderbook = await callSmokeTool(client, TOOL_NAMES.readInspectDeepbookOrderbook, {
152
+ poolKey,
153
+ ticks: 5
154
+ });
155
+ const quote = await callSmokeTool(client, TOOL_NAMES.readQuoteDeepbookAction, {
156
+ poolKey,
157
+ direction: "base_to_quote",
158
+ amountRaw: quoteAmount
159
+ });
160
+ const activityScan = await callSmokeTool(client, TOOL_NAMES.readScanSuiAccountActivity, {
161
+ account: smokeAddress,
162
+ limit: ACTIVITY_SMOKE_LIMIT
163
+ });
164
+ const activitySummary = await callSmokeTool(client, TOOL_NAMES.readSummarizeSuiActivityScan, {
165
+ limit: ACTIVITY_SMOKE_LIMIT
166
+ });
167
+ assertSmokeOkStatus(wallet, TOOL_NAMES.readSummarizeWalletAssets);
168
+ markCompleted(TOOL_NAMES.readSummarizeWalletAssets);
169
+ assertSmokeOkStatus(orderbook, TOOL_NAMES.readInspectDeepbookOrderbook);
170
+ markCompleted(TOOL_NAMES.readInspectDeepbookOrderbook);
171
+ assertSmokeOkStatus(quote, TOOL_NAMES.readQuoteDeepbookAction);
172
+ markCompleted(TOOL_NAMES.readQuoteDeepbookAction);
173
+ activitySmoke.scan = summarizeActivitySmokePayload(activityScan, TOOL_NAMES.readScanSuiAccountActivity, {
174
+ expectedAccountSource: "explicit_filter",
175
+ requireAnalysis: false,
176
+ expectNoDetails: true
177
+ });
178
+ markCompleted(TOOL_NAMES.readScanSuiAccountActivity);
179
+ activitySmoke.summary = summarizeActivitySmokePayload(activitySummary, TOOL_NAMES.readSummarizeSuiActivityScan, {
180
+ expectedAccountSource: "active_account_context",
181
+ requireAnalysis: true,
182
+ expectNoDetails: true
183
+ });
184
+ markCompleted(TOOL_NAMES.readSummarizeSuiActivityScan);
185
+ if (smokeFunctionTarget) {
186
+ const functionActivityScan = await callSmokeTool(client, TOOL_NAMES.readScanSuiFunctionActivity, {
187
+ function: smokeFunctionTarget,
188
+ account: smokeAddress,
189
+ limit: ACTIVITY_SMOKE_LIMIT
190
+ });
191
+ const functionActivitySummary = await callSmokeTool(client, TOOL_NAMES.readSummarizeSuiFunctionActivityScan, {
192
+ function: smokeFunctionTarget,
193
+ limit: ACTIVITY_SMOKE_LIMIT
194
+ });
195
+ functionActivitySmoke.scan = summarizeActivitySmokePayload(functionActivityScan, TOOL_NAMES.readScanSuiFunctionActivity, {
196
+ expectedAccountSource: "explicit_filter",
197
+ expectedRelationship: "sent",
198
+ requireFunction: true,
199
+ requireAnalysis: false,
200
+ expectNoDetails: true
201
+ });
202
+ markCompleted(TOOL_NAMES.readScanSuiFunctionActivity);
203
+ functionActivitySmoke.summary = summarizeActivitySmokePayload(functionActivitySummary, TOOL_NAMES.readSummarizeSuiFunctionActivityScan, {
204
+ expectedAccountSource: "active_account_context",
205
+ expectedRelationship: "sent",
206
+ requireFunction: true,
207
+ requireAnalysis: true,
208
+ expectNoDetails: true
209
+ });
210
+ markCompleted(TOOL_NAMES.readSummarizeSuiFunctionActivityScan);
211
+ }
212
+ if (inspectDigest) {
213
+ const inspected = await callSmokeTool(client, TOOL_NAMES.readInspectSuiTransaction, {
214
+ digest: inspectDigest,
215
+ account: smokeAddress
216
+ });
217
+ assertSmokeOkStatus(inspected, TOOL_NAMES.readInspectSuiTransaction);
218
+ markCompleted(TOOL_NAMES.readInspectSuiTransaction);
219
+ }
220
+ else if (inspectRandomLatest) {
221
+ const randomLatestDigest = await pickRandomLatestTransactionDigest({
222
+ url: config.graphqlUrl,
223
+ expectedChainIdentifier: config.expectedChainIdentifier
224
+ });
225
+ const inspected = await callSmokeTool(client, TOOL_NAMES.readInspectSuiTransaction, {
226
+ digest: randomLatestDigest
227
+ });
228
+ assertSmokeOkStatus(inspected, TOOL_NAMES.readInspectSuiTransaction);
229
+ markCompleted(TOOL_NAMES.readInspectSuiTransaction);
230
+ }
231
+ tryWriteSmokeResult({
232
+ accountBoundSwapReview,
233
+ ok: true,
234
+ startedAt: startedAt.toISOString(),
235
+ completedAt: new Date().toISOString(),
236
+ chainIdentifier,
237
+ env: smokeEnvPresence(),
238
+ plannedTools: [...plannedTools],
239
+ attemptedTools,
240
+ tools: completedTools,
241
+ activitySmoke,
242
+ functionActivitySmoke
243
+ });
244
+ process.stdout.write(`${JSON.stringify({
245
+ ok: true,
246
+ plannedTools: [...plannedTools],
247
+ attemptedTools,
248
+ tools: completedTools,
249
+ activitySmoke,
250
+ functionActivitySmoke
251
+ }, null, 2)}\n`);
252
+ }
253
+ finally {
254
+ await Promise.allSettled([
255
+ ...(server ? [server.close()] : []),
256
+ client.close(),
257
+ ]);
258
+ activityStore?.close();
259
+ if (smokeDbDir)
260
+ rmSync(smokeDbDir, { recursive: true, force: true });
261
+ }
262
+ }
263
+ async function callSmokeTool(client, name, args) {
264
+ attemptedTools.push(name);
265
+ return callTool(client, name, args);
266
+ }
267
+ async function callTool(client, name, args) {
268
+ const result = await client.callTool({ name, arguments: args });
269
+ const content = result.content;
270
+ const text = content[0]?.type === "text" ? content[0].text : undefined;
271
+ if (!text) {
272
+ fail("tool_failure", `Tool ${name} did not return text JSON content`);
273
+ }
274
+ try {
275
+ return JSON.parse(text);
276
+ }
277
+ catch (error) {
278
+ throw new SmokeResponseShapeError(`Tool ${name} did not return valid text JSON content: ${error instanceof Error ? error.message : String(error)}`);
279
+ }
280
+ }
281
+ function markCompleted(name) {
282
+ if (!completedTools.includes(name)) {
283
+ completedTools.push(name);
284
+ }
285
+ }
286
+ function requiredEnv(name) {
287
+ const value = process.env[name];
288
+ if (!value) {
289
+ fail("missing_env", `${name} is required for npm run smoke:mainnet`);
290
+ }
291
+ return value;
292
+ }
293
+ function truthyEnv(name) {
294
+ const value = process.env[name];
295
+ return value === "1" || value === "true" || value === "TRUE" || value === "yes" || value === "YES";
296
+ }
297
+ async function pickRandomLatestTransactionDigest(input) {
298
+ const { client } = await verifyMainnetGraphqlEndpoint({
299
+ url: input.url,
300
+ expectedChainIdentifier: input.expectedChainIdentifier
301
+ });
302
+ const result = await client.query({
303
+ query: `
304
+ query SuiMcpSmokeLatestTransactionSample($last: Int!) {
305
+ transactions(last: $last) {
306
+ nodes { digest }
307
+ }
308
+ }
309
+ `,
310
+ variables: { last: 20 }
311
+ });
312
+ if (result.errors && result.errors.length > 0) {
313
+ fail("tool_failure", `Latest transaction sample query failed: ${result.errors.map((error) => error.message).join("; ")}`);
314
+ }
315
+ const digests = result.data?.transactions?.nodes
316
+ ?.flatMap((node) => typeof node.digest === "string" && node.digest.length > 0 ? [node.digest] : []) ?? [];
317
+ if (digests.length === 0) {
318
+ fail("tool_failure", "Latest transaction sample query returned no transaction digests");
319
+ }
320
+ return digests[randomInt(digests.length)] ?? fail("tool_failure", "Latest transaction sample selection failed");
321
+ }
322
+ function loadSmokeBootConfig() {
323
+ try {
324
+ return loadBootConfig();
325
+ }
326
+ catch (error) {
327
+ throw new SmokeMainnetError("config_error", error instanceof Error ? error.message : String(error));
328
+ }
329
+ }
330
+ function fail(category, message) {
331
+ throw new SmokeMainnetError(category, message);
332
+ }
333
+ function smokeEnvPresence() {
334
+ return {
335
+ SUI_GRPC_URL: process.env.SUI_GRPC_URL !== undefined,
336
+ SUI_GRAPHQL_URL: process.env.SUI_GRAPHQL_URL !== undefined,
337
+ SMOKE_SUI_ADDRESS: process.env.SMOKE_SUI_ADDRESS !== undefined,
338
+ SMOKE_DEEPBOOK_POOL_KEY: process.env.SMOKE_DEEPBOOK_POOL_KEY !== undefined,
339
+ SMOKE_QUOTE_AMOUNT: process.env.SMOKE_QUOTE_AMOUNT !== undefined,
340
+ SMOKE_INSPECT_DIGEST: process.env.SMOKE_INSPECT_DIGEST !== undefined,
341
+ SMOKE_INSPECT_RANDOM_LATEST: process.env.SMOKE_INSPECT_RANDOM_LATEST !== undefined,
342
+ SMOKE_FUNCTION_TARGET: process.env.SMOKE_FUNCTION_TARGET !== undefined,
343
+ SMOKE_SWAP_PROTOCOL: process.env.SMOKE_SWAP_PROTOCOL !== undefined,
344
+ SMOKE_SWAP_FROM_SYMBOL: process.env.SMOKE_SWAP_FROM_SYMBOL !== undefined,
345
+ SMOKE_SWAP_TO_SYMBOL: process.env.SMOKE_SWAP_TO_SYMBOL !== undefined,
346
+ SMOKE_SWAP_AMOUNT_DISPLAY: process.env.SMOKE_SWAP_AMOUNT_DISPLAY !== undefined
347
+ };
348
+ }
349
+ function tryWriteSmokeResult(record) {
350
+ try {
351
+ writeSmokeResult(record);
352
+ }
353
+ catch (error) {
354
+ process.stderr.write(`smoke:mainnet result recording failed: ${error instanceof Error ? error.message : String(error)}\n`);
355
+ }
356
+ }
357
+ function writeSmokeResult(record) {
358
+ const directory = join(process.cwd(), ".WORK", "smoke-results");
359
+ mkdirSync(directory, { recursive: true });
360
+ writeFileSync(join(directory, `${record.completedAt ?? new Date().toISOString()}.json`.replace(/:/g, "-")), `${JSON.stringify(record, null, 2)}\n`);
361
+ }
362
+ function smokeErrorCategory(error) {
363
+ if (error instanceof SuiEndpointError) {
364
+ return error.kind;
365
+ }
366
+ if (error instanceof SmokeResponseShapeError) {
367
+ return "tool_failure";
368
+ }
369
+ if (error instanceof SmokeReviewConfigError)
370
+ return "config_error";
371
+ if (error instanceof SmokeMainnetError) {
372
+ return error.category;
373
+ }
374
+ return "runtime_error";
375
+ }
376
+ main().catch((error) => {
377
+ tryWriteSmokeResult({
378
+ ok: false,
379
+ startedAt: startedAt.toISOString(),
380
+ completedAt: new Date().toISOString(),
381
+ env: smokeEnvPresence(),
382
+ attemptedTools,
383
+ tools: completedTools,
384
+ plannedTools: [...plannedTools],
385
+ activitySmoke,
386
+ functionActivitySmoke,
387
+ errorCategory: smokeErrorCategory(error)
388
+ });
389
+ process.stderr.write(`smoke:mainnet failed: ${error instanceof Error ? error.message : String(error)}\n`);
390
+ process.exit(1);
391
+ });