@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.
- package/LICENSE +21 -0
- package/LICENSES/@mysten-bcs-2.0.5-Apache-2.0.txt +205 -0
- package/LICENSES/@mysten-sui-2.17.0-Apache-2.0.txt +201 -0
- package/LICENSES/@mysten-utils-0.3.3-Apache-2.0.txt +205 -0
- package/LICENSES/fancy-canvas-2.1.0-MIT.txt +7 -0
- package/LICENSES/lightweight-charts-5.2.0-NOTICE.txt +2 -0
- package/README.md +288 -0
- package/dist/adapters/adapterLifecycleValidators.js +5 -0
- package/dist/adapters/adapterPromptSurfaces.js +60 -0
- package/dist/adapters/deepbook/deepbookHumanReviewProducer.js +178 -0
- package/dist/adapters/deepbook/deepbookQuotePolicy.js +112 -0
- package/dist/adapters/deepbook/deepbookReviewEvidence.js +507 -0
- package/dist/adapters/deepbook/deepbookReviewLifecycle.js +85 -0
- package/dist/adapters/deepbook/deepbookSwapIntent.js +79 -0
- package/dist/adapters/deepbook/deepbookTransactionMaterialProducer.js +254 -0
- package/dist/adapters/intentPlanFactories.js +51 -0
- package/dist/adapters/reviewAdapters.js +47 -0
- package/dist/core/action/adapterLifecycleValidation.js +12 -0
- package/dist/core/action/contractNameRegistry.js +151 -0
- package/dist/core/action/forbiddenFields.js +43 -0
- package/dist/core/action/humanReadableReviewEvidence.js +193 -0
- package/dist/core/action/humanReadableReviewProjectionVerifier.js +29 -0
- package/dist/core/action/ptbVisualizationProducer.js +71 -0
- package/dist/core/action/receiptPtbGraph.js +29 -0
- package/dist/core/action/reviewCheckResults.js +6 -0
- package/dist/core/action/reviewStateValidation.js +11 -0
- package/dist/core/action/reviewTimeSimulationEvidence.js +470 -0
- package/dist/core/action/schemas.js +491 -0
- package/dist/core/action/signableAdapterContract.js +998 -0
- package/dist/core/action/suiChainReceiptEvidence.js +106 -0
- package/dist/core/action/suiChainReceiptMapping.js +107 -0
- package/dist/core/action/suiChainReceiptReader.js +211 -0
- package/dist/core/action/suiChainReceiptVerifier.js +178 -0
- package/dist/core/action/swapHumanReadableReviewProjection.js +130 -0
- package/dist/core/action/swapQuotePolicyEvidence.js +271 -0
- package/dist/core/action/transactionFunding.js +244 -0
- package/dist/core/action/transactionObjectOwnershipEvidence.js +256 -0
- package/dist/core/action/transactionObjectOwnershipProducer.js +323 -0
- package/dist/core/action/types.js +33 -0
- package/dist/core/action/walletReviewContractAssembler.js +286 -0
- package/dist/core/activity/accountAssetTimeline.js +157 -0
- package/dist/core/activity/accountAssetTimelineUsdcReferences.js +120 -0
- package/dist/core/activity/activityStore.js +16 -0
- package/dist/core/activity/externalActivityCoverage.js +76 -0
- package/dist/core/activity/externalActivityTransactionStream.js +82 -0
- package/dist/core/activity/localDataService.js +296 -0
- package/dist/core/activity/localDataTypes.js +11 -0
- package/dist/core/activity/localDataValidation.js +439 -0
- package/dist/core/activity/schemaVersion.js +2 -0
- package/dist/core/activity/sqliteActivityStore.js +1068 -0
- package/dist/core/activity/sqliteActivityStoreRows.js +389 -0
- package/dist/core/activity/sqliteActivityStoreSchema.js +367 -0
- package/dist/core/activity/sqliteActivityStoreTypes.js +5 -0
- package/dist/core/activity/suiFunctionTarget.js +43 -0
- package/dist/core/activity/transactionActivityAccountEffects.js +186 -0
- package/dist/core/activity/transactionActivityAnalysis.js +295 -0
- package/dist/core/activity/transactionActivityClassifier.js +306 -0
- package/dist/core/activity/transactionActivityDetails.js +229 -0
- package/dist/core/activity/transactionActivityProtocolRules.js +218 -0
- package/dist/core/activity/transactionActivityScanPolicy.js +170 -0
- package/dist/core/activity/transactionActivityService.js +379 -0
- package/dist/core/activity/transactionActivityTypes.js +18 -0
- package/dist/core/eventlog/sink.js +35 -0
- package/dist/core/evidence/settlementFamilies.js +85 -0
- package/dist/core/evidence/userAnswerUse.js +1 -0
- package/dist/core/numeric/rawU64.js +63 -0
- package/dist/core/preferences/preferencesStore.js +26 -0
- package/dist/core/preferences/sqlitePreferencesRepository.js +136 -0
- package/dist/core/proposal/externalProposalReview.js +347 -0
- package/dist/core/proposal/schemas.js +208 -0
- package/dist/core/proposal/types.js +35 -0
- package/dist/core/read/amounts.js +14 -0
- package/dist/core/read/coinMetadata.js +60 -0
- package/dist/core/read/deepbookOfficialIndexerSource.js +373 -0
- package/dist/core/read/deepbookRawQuoteClient.js +86 -0
- package/dist/core/read/deepbookReadHelpers.js +321 -0
- package/dist/core/read/deepbookRegistry.js +157 -0
- package/dist/core/read/deepbookSourceOwners.js +159 -0
- package/dist/core/read/deepbookUsdcChartService.js +342 -0
- package/dist/core/read/intentEvidenceResponseFormatting.js +228 -0
- package/dist/core/read/readCardInputs.js +19 -0
- package/dist/core/read/readCardResult.js +40 -0
- package/dist/core/read/readResponseGuidance.js +402 -0
- package/dist/core/read/readService.js +1639 -0
- package/dist/core/read/readServiceTypes.js +88 -0
- package/dist/core/read/settlementParityFormatting.js +82 -0
- package/dist/core/read/walletReadHelpers.js +99 -0
- package/dist/core/review/reviewChecks.js +45 -0
- package/dist/core/review/reviewComputation.js +38 -0
- package/dist/core/review/reviewComputationResult.js +87 -0
- package/dist/core/session/cardSession.js +31 -0
- package/dist/core/session/cardSessionStore.js +204 -0
- package/dist/core/session/keyedRecordStore.js +18 -0
- package/dist/core/session/liveReviewSessionContract.js +3 -0
- package/dist/core/session/localSession.js +31 -0
- package/dist/core/session/privateReviewArtifacts.js +75 -0
- package/dist/core/session/reviewValidity.js +49 -0
- package/dist/core/session/sessionErrors.js +9 -0
- package/dist/core/session/sessionRecordStore.js +40 -0
- package/dist/core/session/sessionStore.js +655 -0
- package/dist/core/session/settingsSession.js +1 -0
- package/dist/core/session/settingsSessions.js +45 -0
- package/dist/core/session/sqliteCardStore.js +88 -0
- package/dist/core/session/sqliteSessionStore.js +213 -0
- package/dist/core/session/sqliteTransactionMaterialStore.js +64 -0
- package/dist/core/session/sqliteWalletWorkflowStore.js +821 -0
- package/dist/core/session/status.js +60 -0
- package/dist/core/session/transactionMaterialStore.js +221 -0
- package/dist/core/session/transactionRequest.js +72 -0
- package/dist/core/session/wait.js +79 -0
- package/dist/core/session/walletConnection.js +92 -0
- package/dist/core/session/walletRuntime.js +38 -0
- package/dist/core/session/walletWorkflow.js +608 -0
- package/dist/core/session/workflowState.js +80 -0
- package/dist/core/session/workflowView.js +150 -0
- package/dist/core/suiAddress.js +18 -0
- package/dist/core/suiEndpoint.js +72 -0
- package/dist/mcp/activeAccountResponse.js +24 -0
- package/dist/mcp/prompts.js +146 -0
- package/dist/mcp/registerTool.js +19 -0
- package/dist/mcp/resources.js +72 -0
- package/dist/mcp/responseGuidance.js +326 -0
- package/dist/mcp/result.js +17 -0
- package/dist/mcp/schemas.js +11 -0
- package/dist/mcp/server.js +32 -0
- package/dist/mcp/serverInfo.js +131 -0
- package/dist/mcp/toolErrors.js +118 -0
- package/dist/mcp/toolNames.js +58 -0
- package/dist/mcp/tools/account/index.js +44 -0
- package/dist/mcp/tools/action/prepareSuiActionReview.js +126 -0
- package/dist/mcp/tools/read/commonSchemas.js +43 -0
- package/dist/mcp/tools/read/deepbookReadTools.js +686 -0
- package/dist/mcp/tools/read/index.js +14 -0
- package/dist/mcp/tools/read/readToolHelpers.js +97 -0
- package/dist/mcp/tools/read/reviewActivityTools.js +179 -0
- package/dist/mcp/tools/read/serverStatusTools.js +100 -0
- package/dist/mcp/tools/read/transactionActivityOutput.js +371 -0
- package/dist/mcp/tools/read/transactionActivityTools.js +858 -0
- package/dist/mcp/tools/read/walletReadTools.js +734 -0
- package/dist/mcp/tools/session/executionResultTools.js +44 -0
- package/dist/mcp/tools/session/index.js +8 -0
- package/dist/mcp/tools/session/shared.js +36 -0
- package/dist/mcp/tools/session/statusTools.js +69 -0
- package/dist/mcp/tools/session/walletConnectionTools.js +69 -0
- package/dist/mcp/tools/settings/index.js +66 -0
- package/dist/mcp-app/account.html +3133 -0
- package/dist/mcp-app/account.notices.txt +973 -0
- package/dist/mcp-app/chart.html +3354 -0
- package/dist/mcp-app/chart.notices.txt +1194 -0
- package/dist/mcp-app/connect.html +3179 -0
- package/dist/mcp-app/connect.notices.txt +1012 -0
- package/dist/mcp-app/receipt.html +8430 -0
- package/dist/mcp-app/receipt.notices.txt +3549 -0
- package/dist/mcp-app/review.html +8430 -0
- package/dist/mcp-app/review.notices.txt +3549 -0
- package/dist/mcp-ui/contracts.js +31 -0
- package/dist/mcp-ui/readCards.js +28 -0
- package/dist/mcp-ui/tools.js +134 -0
- package/dist/review-app/brand-dark.svg +1 -0
- package/dist/review-app/brand-light.svg +1 -0
- package/dist/review-app/favicon.svg +1 -0
- package/dist/review-app/settings.css +1 -0
- package/dist/review-app/settings.js +1 -0
- package/dist/review-app/ui.css +809 -0
- package/dist/review-server/assets.js +48 -0
- package/dist/review-server/html.js +45 -0
- package/dist/review-server/http.js +47 -0
- package/dist/review-server/middleware/hostOrigin.js +48 -0
- package/dist/review-server/middleware/reviewToken.js +7 -0
- package/dist/review-server/reviewServerPolicy.js +1 -0
- package/dist/review-server/server.js +72 -0
- package/dist/review-server/settingsApi.js +158 -0
- package/dist/runtime/application.js +203 -0
- package/dist/runtime/config.js +97 -0
- package/dist/runtime/localSettingsService.js +198 -0
- package/dist/runtime/logger.js +66 -0
- package/dist/runtime/reviewDependencies.js +58 -0
- package/dist/runtime/reviewServerAcquire.js +93 -0
- package/dist/runtime/runtimeTermination.js +60 -0
- package/dist/runtime/shared/authenticatedFetch.js +127 -0
- package/dist/runtime/shared/control.js +93 -0
- package/dist/runtime/shared/dataAccess.js +66 -0
- package/dist/runtime/shared/mcpHttp.js +84 -0
- package/dist/runtime/shared/ownerLease.js +50 -0
- package/dist/runtime/shared/server.js +98 -0
- package/dist/runtime/shared/stdio.js +113 -0
- package/dist/runtime/smokeMainnetRead.js +391 -0
- package/dist/runtime/smokeMainnetReadAssertions.js +306 -0
- package/dist/runtime/smokeReview.js +40 -0
- package/dist/runtime/start.js +90 -0
- package/dist/runtime/suiEndpoint.js +97 -0
- package/dist/runtime/suiTransactionGraphqlMapping.js +200 -0
- package/dist/runtime/suiTransactionGraphqlQueries.js +231 -0
- package/dist/runtime/suiTransactionGraphqlSource.js +148 -0
- package/dist/runtime/walletConnectConfig.js +3 -0
- package/dist/runtime/walletConnectStorage.js +99 -0
- package/dist/runtime/walletConnectTransport.js +128 -0
- package/dist/runtime/walletSdkChild.js +3 -0
- package/dist/runtime/walletSdkChildRuntime.js +160 -0
- package/dist/runtime/walletSdkIpc.js +26 -0
- package/dist/runtime/walletSdkProcess.js +358 -0
- package/docs/AGENT_BEHAVIOR.md +524 -0
- package/docs/AGENT_DEVELOPMENT_POLICY.md +815 -0
- package/docs/FRONTEND_POLICY.md +534 -0
- package/docs/LOCAL_DB_ARCHITECTURE.md +381 -0
- package/docs/MCP_SETUP.md +742 -0
- package/docs/MCP_TOOLS.md +1318 -0
- package/docs/SDK_API.md +206 -0
- package/docs/SIGNABLE_ADAPTER_CONTRACT.md +396 -0
- package/docs/TRANSACTION_ACTIVITY_LOG.md +194 -0
- package/docs/UTILITY_INDEX.md +275 -0
- package/docs/WALLET_CONNECTION.md +238 -0
- package/docs/golden-scenarios/BEHAVIOR_MATRIX.md +166 -0
- package/docs/golden-scenarios/INTENT_EVIDENCE_GOLDEN_ANSWERS.md +161 -0
- package/docs/golden-scenarios/INTENT_EVIDENCE_MATRIX.md +259 -0
- package/package.json +79 -0
- package/protocols/deepbook-margin.md +15 -0
- 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
|
+
}
|