@stelis/say-ur-intent 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -39
- package/dist/adapters/adapterLifecycleValidators.js +7 -0
- package/dist/adapters/adapterPromptSurfaces.js +71 -0
- package/dist/adapters/deepbook/deepbookHumanReviewProducer.js +175 -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 +269 -0
- package/dist/adapters/flowx/flowxSwapHumanReviewProducer.js +176 -0
- package/dist/adapters/flowx/flowxSwapIntent.js +79 -0
- package/dist/adapters/flowx/flowxSwapQuotePolicy.js +104 -0
- package/dist/adapters/flowx/flowxSwapReviewEvidence.js +468 -0
- package/dist/adapters/flowx/flowxSwapReviewLifecycle.js +85 -0
- package/dist/adapters/flowx/flowxSwapTransactionMaterialProducer.js +362 -0
- package/dist/adapters/intentPlanFactories.js +59 -0
- package/dist/adapters/reviewAdapters.js +81 -0
- package/dist/core/action/adapterLifecycleValidation.js +12 -0
- package/dist/core/action/forbiddenFields.js +43 -0
- package/dist/core/action/humanReadableReviewEvidence.js +203 -0
- package/dist/core/action/humanReadableReviewProjectionVerifier.js +29 -0
- package/dist/core/action/ptbVisualizationProducer.js +66 -0
- package/dist/core/action/reviewCheckResults.js +6 -0
- package/dist/core/action/reviewStateValidation.js +11 -0
- package/dist/core/action/reviewTimeSimulationEvidence.js +471 -0
- package/dist/core/action/schemas.js +529 -0
- package/dist/core/action/signableAdapterContract.js +993 -0
- package/dist/core/action/swapHumanReadableReviewProjection.js +124 -0
- package/dist/core/action/swapQuotePolicyEvidence.js +278 -0
- package/dist/core/action/transactionObjectOwnershipEvidence.js +247 -0
- package/dist/core/action/transactionObjectOwnershipProducer.js +329 -0
- package/dist/core/action/types.js +35 -0
- package/dist/core/action/walletReviewContractAssembler.js +282 -0
- package/dist/core/activity/activityStore.js +15 -0
- package/dist/core/activity/localDataService.js +258 -0
- package/dist/core/activity/localDataTypes.js +11 -0
- package/dist/core/activity/localDataValidation.js +396 -0
- package/dist/core/activity/schemaVersion.js +1 -0
- package/dist/core/activity/sqliteActivityStore.js +820 -0
- package/dist/core/activity/sqliteActivityStoreRows.js +430 -0
- package/dist/core/activity/sqliteActivityStoreSchema.js +258 -0
- package/dist/core/activity/sqliteActivityStoreTypes.js +5 -0
- package/dist/core/activity/suiFunctionTarget.js +43 -0
- package/dist/core/activity/transactionActivityAccountEffects.js +189 -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 +87 -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/deepbookRawQuoteClient.js +86 -0
- package/dist/core/read/deepbookReadHelpers.js +265 -0
- package/dist/core/read/deepbookRegistry.js +133 -0
- package/dist/core/read/flowxQuoteClient.js +117 -0
- package/dist/core/read/flowxReadHelpers.js +145 -0
- package/dist/core/read/flowxRegistry.js +174 -0
- package/dist/core/read/intentEvidenceResponseFormatting.js +228 -0
- package/dist/core/read/readResponseGuidance.js +451 -0
- package/dist/core/read/readService.js +1164 -0
- package/dist/core/read/readServiceTypes.js +59 -0
- package/dist/core/read/settlementParityFormatting.js +82 -0
- package/dist/core/read/walletReadHelpers.js +99 -0
- package/dist/core/review/reviewChecks.js +54 -0
- package/dist/core/review/reviewComputation.js +38 -0
- package/dist/core/review/reviewComputationResult.js +87 -0
- package/dist/core/session/localSession.js +31 -0
- package/dist/core/session/privateReviewArtifacts.js +73 -0
- package/dist/core/session/sessionErrors.js +9 -0
- package/dist/core/session/sessionStore.js +821 -0
- package/dist/core/session/settingsSession.js +1 -0
- package/dist/core/session/settingsSessions.js +43 -0
- package/dist/core/session/status.js +86 -0
- package/dist/core/session/transactionMaterialStore.js +205 -0
- package/dist/core/session/wait.js +102 -0
- package/dist/core/session/walletIdentity.js +103 -0
- package/dist/core/session/walletIdentitySessions.js +189 -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 +381 -0
- package/dist/mcp/result.js +17 -0
- package/dist/mcp/schemas.js +8 -0
- package/dist/mcp/server.js +30 -0
- package/dist/mcp/serverInfo.js +123 -0
- package/dist/mcp/toolErrors.js +105 -0
- package/dist/mcp/toolNames.js +50 -0
- package/dist/mcp/tools/account/index.js +44 -0
- package/dist/mcp/tools/action/prepareSuiActionReview.js +120 -0
- package/dist/mcp/tools/read/commonSchemas.js +43 -0
- package/dist/mcp/tools/read/deepbookReadTools.js +453 -0
- package/dist/mcp/tools/read/flowxReadTools.js +135 -0
- package/dist/mcp/tools/read/index.js +16 -0
- package/dist/mcp/tools/read/readToolHelpers.js +68 -0
- package/dist/mcp/tools/read/reviewActivityTools.js +176 -0
- package/dist/mcp/tools/read/serverStatusTools.js +103 -0
- package/dist/mcp/tools/read/transactionActivityOutput.js +300 -0
- package/dist/mcp/tools/read/transactionActivityTools.js +544 -0
- package/dist/mcp/tools/read/walletReadTools.js +733 -0
- package/dist/mcp/tools/session/executionResultTools.js +92 -0
- package/dist/mcp/tools/session/index.js +8 -0
- package/dist/mcp/tools/session/shared.js +79 -0
- package/dist/mcp/tools/session/statusTools.js +134 -0
- package/dist/mcp/tools/session/walletIdentityTools.js +119 -0
- package/dist/mcp/tools/settings/index.js +64 -0
- package/dist/review-app/analysis.css +1 -0
- package/dist/review-app/analysis.js +1 -0
- package/dist/review-app/arc-BjIacwQm.js +1 -0
- package/dist/review-app/architecture-U656AL7Q-aSB9x1OK.js +1 -0
- package/dist/review-app/architectureDiagram-VXUJARFQ-C5W6re2I.js +36 -0
- package/dist/review-app/array-BmXUUrU6.js +1 -0
- package/dist/review-app/blockDiagram-VD42YOAC-20MLNcUm.js +122 -0
- package/dist/review-app/c4Diagram-YG6GDRKO-BZXRrcck.js +10 -0
- package/dist/review-app/channel-lk2p_CUu.js +1 -0
- package/dist/review-app/chunk-4BX2VUAB-BPITOdjX.js +1 -0
- package/dist/review-app/chunk-55IACEB6-Dz-pyw5k.js +1 -0
- package/dist/review-app/chunk-76Q3JFCE-cK_X1P_l.js +1 -0
- package/dist/review-app/chunk-ABZYJK2D-Dt4W53JI.js +81 -0
- package/dist/review-app/chunk-ATLVNIR6-fZHLXURb.js +1 -0
- package/dist/review-app/chunk-B4BG7PRW-BbgcjusC.js +165 -0
- package/dist/review-app/chunk-BJD4TVEz.js +1 -0
- package/dist/review-app/chunk-CVBHYZKI-CViawAKX.js +1 -0
- package/dist/review-app/chunk-DI55MBZ5-C5aoul-d.js +220 -0
- package/dist/review-app/chunk-FMBD7UC4-Chxmw62A.js +15 -0
- package/dist/review-app/chunk-FPAJGGOC-DDHjQ09H.js +80 -0
- package/dist/review-app/chunk-FWNWRKHM-CVVQUptk.js +1 -0
- package/dist/review-app/chunk-HN2XXSSU-yzNpjaSZ.js +1 -0
- package/dist/review-app/chunk-JA3XYJ7Z-C5ZJdU01.js +70 -0
- package/dist/review-app/chunk-JZLCHNYA-BBST4Cnk.js +54 -0
- package/dist/review-app/chunk-LBM3YZW2-CdwAPuHr.js +1 -0
- package/dist/review-app/chunk-LHMN2FUI-BtB5uDcp.js +1 -0
- package/dist/review-app/chunk-O7ZBX7Z2-pxdK4Sa3.js +1 -0
- package/dist/review-app/chunk-QN33PNHL-CbVv3uGK.js +1 -0
- package/dist/review-app/chunk-QXUST7PY-DKM2-t2c.js +7 -0
- package/dist/review-app/chunk-QZHKN3VN-C5ni2pN_.js +1 -0
- package/dist/review-app/chunk-S3R3BYOJ-BWvOhDs0.js +2 -0
- package/dist/review-app/chunk-S6J4BHB3-D9Fk0YeD.js +1 -0
- package/dist/review-app/chunk-T53DSG4Q-C1qEyzyV.js +1 -0
- package/dist/review-app/chunk-TZMSLE5B-B--7eU69.js +1 -0
- package/dist/review-app/classDiagram-2ON5EDUG-DlL1m2bp.js +1 -0
- package/dist/review-app/classDiagram-v2-WZHVMYZB-FXRskT1j.js +1 -0
- package/dist/review-app/clone-BZZb7gpZ.js +1 -0
- package/dist/review-app/cose-bilkent-S5V4N54A-CRIb8XEO.js +1 -0
- package/dist/review-app/cytoscape.esm-C7jYqDP5.js +321 -0
- package/dist/review-app/dagre-6UL2VRFP-FNCAXbdE.js +4 -0
- package/dist/review-app/dagre-Be46QtUd.js +1 -0
- package/dist/review-app/defaultLocale-BaWNtAUL.js +1 -0
- package/dist/review-app/diagram-PSM6KHXK-ylLWjiNM.js +24 -0
- package/dist/review-app/diagram-QEK2KX5R-BCDcESxs.js +43 -0
- package/dist/review-app/diagram-S2PKOQOG-Vdrc-vrO.js +24 -0
- package/dist/review-app/dist-WPc74x_f.js +1 -0
- package/dist/review-app/erDiagram-Q2GNP2WA-E5ZsUbDF.js +60 -0
- package/dist/review-app/flatten-DHf9IeNI.js +1 -0
- package/dist/review-app/flowDiagram-NV44I4VS-DBSQuj6x.js +162 -0
- package/dist/review-app/ganttDiagram-LVOFAZNH-CKUOsqwl.js +267 -0
- package/dist/review-app/gitGraph-F6HP7TQM-DsAD6qK1.js +1 -0
- package/dist/review-app/gitGraphDiagram-NY62KEGX-BCeIMWdl.js +65 -0
- package/dist/review-app/graphlib-CiX5CXxR.js +1 -0
- package/dist/review-app/http-DMvwuuFk.js +1 -0
- package/dist/review-app/identity-DY8PXc6t.js +1 -0
- package/dist/review-app/info-NVLQJR56-Dlx1nZic.js +1 -0
- package/dist/review-app/infoDiagram-F6ZHWCRC-CAuANIrz.js +2 -0
- package/dist/review-app/init-BvqephKz.js +1 -0
- package/dist/review-app/journeyDiagram-XKPGCS4Q-C-Z9phnx.js +139 -0
- package/dist/review-app/kanban-definition-3W4ZIXB7-DufgZABq.js +89 -0
- package/dist/review-app/katex-B-Z-NXXN.js +257 -0
- package/dist/review-app/line-DiIv3Jgw.js +1 -0
- package/dist/review-app/linear-Cv-UPvo1.js +1 -0
- package/dist/review-app/math-kmyYrkHL.js +1 -0
- package/dist/review-app/mermaid-parser.core-DkwUYTPl.js +4 -0
- package/dist/review-app/mindmap-definition-VGOIOE7T-TM_CqdmV.js +68 -0
- package/dist/review-app/ordinal-BliTlkoG.js +1 -0
- package/dist/review-app/packet-BFZMPI3H-DqbnU92v.js +1 -0
- package/dist/review-app/path-AEo9W6mQ.js +1 -0
- package/dist/review-app/pie-7BOR55EZ-LJzaLkgr.js +1 -0
- package/dist/review-app/pieDiagram-ADFJNKIX-BAs8OfRS.js +30 -0
- package/dist/review-app/quadrantDiagram-AYHSOK5B-CyUDZP5S.js +7 -0
- package/dist/review-app/radar-NHE76QYJ-DBpHc8_Y.js +1 -0
- package/dist/review-app/reduce-B-HuPpdd.js +1 -0
- package/dist/review-app/requirementDiagram-UZGBJVZJ-BEHix78P.js +64 -0
- package/dist/review-app/review.css +1 -0
- package/dist/review-app/review.js +43 -0
- package/dist/review-app/sankeyDiagram-TZEHDZUN-B2bKbmsm.js +10 -0
- package/dist/review-app/sequenceDiagram-WL72ISMW-DVLOORFJ.js +145 -0
- package/dist/review-app/settings.css +1 -0
- package/dist/review-app/settings.js +1 -0
- package/dist/review-app/src-Buml7cM5.js +1 -0
- package/dist/review-app/stateDiagram-FKZM4ZOC-sFGGp2kV.js +1 -0
- package/dist/review-app/stateDiagram-v2-4FDKWEC3-BHfCF4dX.js +1 -0
- package/dist/review-app/timeline-definition-IT6M3QCI-BESnBijC.js +61 -0
- package/dist/review-app/treemap-KMMF4GRG-wnVLBDeQ.js +1 -0
- package/dist/review-app/walletStatus-CcojOdGy.js +7 -0
- package/dist/review-app/xychartDiagram-PRI3JC2R-BGWVfCx4.js +7 -0
- package/dist/review-server/assets.js +48 -0
- package/dist/review-server/html.js +66 -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 +10 -0
- package/dist/review-server/server.js +568 -0
- package/dist/review-server/settingsApi.js +182 -0
- package/dist/review-server/walletIdentityResponse.js +13 -0
- package/dist/runtime/config.js +103 -0
- package/dist/runtime/localSettingsService.js +198 -0
- package/dist/runtime/logger.js +50 -0
- package/dist/runtime/reviewServerAcquire.js +128 -0
- package/dist/runtime/smokeMainnetRead.js +529 -0
- package/dist/runtime/smokeMainnetReadAssertions.js +308 -0
- package/dist/runtime/start.js +295 -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/docs/AGENT_BEHAVIOR.md +1 -1
- package/docs/AGENT_DEVELOPMENT_POLICY.md +20 -0
- package/docs/FRONTEND_POLICY.md +4 -3
- package/docs/MCP_SETUP.md +59 -7
- package/docs/MCP_TOOLS.md +1 -1
- package/docs/SDK_API.md +5 -1
- package/package.json +3 -2
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { isValidTransactionDigest } from "@mysten/sui/utils";
|
|
3
|
+
import { SuiEndpointError } from "../suiEndpoint.js";
|
|
4
|
+
import { parseSuiAddress } from "../suiAddress.js";
|
|
5
|
+
import { REVIEW_ACTIVITY_LIST_DEFAULT_LIMIT } from "./activityStore.js";
|
|
6
|
+
import { externalActivityTransactionBalanceOwners, externalActivityTransactionTouchesAccount, sanitizeExternalActivityTransactionDetailsForKnownAccount } from "./transactionActivityDetails.js";
|
|
7
|
+
import { attachRequestedAccountEffects, buildRequestedAccountActivity, requestedAccountEffectsForTransaction } from "./transactionActivityAccountEffects.js";
|
|
8
|
+
import { assertCheckpointRange, assertTimestampRange, compareActivityFactsDescending, filterTransactionsForRequestedWindow, incompleteReasonForScan, isMonotonicActivityOrder, normalizeActivityLimit, normalizeCheckpointBound, normalizeTimestampBound, transactionMatchesKnownStorageAccount, windowCompletion } from "./transactionActivityScanPolicy.js";
|
|
9
|
+
import { parseSuiFunctionTarget } from "./suiFunctionTarget.js";
|
|
10
|
+
import { TransactionActivityError, TransactionActivitySourceError } from "./transactionActivityTypes.js";
|
|
11
|
+
import { buildSuiActivityAnalysis } from "./transactionActivityAnalysis.js";
|
|
12
|
+
export { TransactionActivityError, TransactionActivitySourceError } from "./transactionActivityTypes.js";
|
|
13
|
+
export class TransactionActivityService {
|
|
14
|
+
options;
|
|
15
|
+
now;
|
|
16
|
+
scanId;
|
|
17
|
+
constructor(options) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.now = options.now ?? (() => new Date());
|
|
20
|
+
this.scanId = options.scanId ?? (() => randomUUID());
|
|
21
|
+
}
|
|
22
|
+
async inspectSuiTransaction(input) {
|
|
23
|
+
const digest = parseTransactionDigest(input.digest);
|
|
24
|
+
const explicitAccount = input.account === undefined ? undefined : parseAccount(input.account);
|
|
25
|
+
const source = await this.verifySource();
|
|
26
|
+
const fetchedAt = this.now().toISOString();
|
|
27
|
+
const transaction = await this.mapSourceCall(() => this.options.source.getTransaction(digest));
|
|
28
|
+
if (!transaction) {
|
|
29
|
+
return {
|
|
30
|
+
status: "ok",
|
|
31
|
+
fetchedAt,
|
|
32
|
+
source: { ...source, method: "Query.transaction" },
|
|
33
|
+
transaction: { digest, status: "unknown" },
|
|
34
|
+
persistence: { stored: false, reason: "transaction_not_found" }
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const transactionForExplicitAccount = explicitAccount === undefined
|
|
38
|
+
? transaction
|
|
39
|
+
: {
|
|
40
|
+
...transaction,
|
|
41
|
+
accountEffects: requestedAccountEffectsForTransaction(transaction, explicitAccount)
|
|
42
|
+
};
|
|
43
|
+
const known = await this.knownDigestAccountForStorage(explicitAccount, transaction);
|
|
44
|
+
if (!known) {
|
|
45
|
+
return {
|
|
46
|
+
status: "ok",
|
|
47
|
+
fetchedAt,
|
|
48
|
+
source: { ...source, method: "Query.transaction" },
|
|
49
|
+
transaction: transactionForExplicitAccount,
|
|
50
|
+
persistence: { stored: false, reason: "no_known_wallet_relation" }
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const transactionForKnownAccount = {
|
|
54
|
+
...transaction,
|
|
55
|
+
accountEffects: requestedAccountEffectsForTransaction(transaction, known.account.address)
|
|
56
|
+
};
|
|
57
|
+
const scan = await this.options.activityStore.recordExternalActivityScan({
|
|
58
|
+
scanId: this.scanId(),
|
|
59
|
+
kind: "digest_lookup",
|
|
60
|
+
account: known.account.address,
|
|
61
|
+
relationship: known.relationship,
|
|
62
|
+
inputDigest: digest,
|
|
63
|
+
limit: 1,
|
|
64
|
+
endpointHost: source.endpointHost,
|
|
65
|
+
chainIdentifier: source.chainIdentifier,
|
|
66
|
+
fetchedAt,
|
|
67
|
+
hasMore: false,
|
|
68
|
+
windowComplete: true,
|
|
69
|
+
transactions: [await this.transactionInputForKnownAccount(transactionForKnownAccount, known.relationship, known.account.address)]
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
status: "ok",
|
|
73
|
+
fetchedAt,
|
|
74
|
+
source: { ...source, method: "Query.transaction" },
|
|
75
|
+
transaction: transactionForKnownAccount,
|
|
76
|
+
persistence: {
|
|
77
|
+
stored: true,
|
|
78
|
+
account: known.account.address,
|
|
79
|
+
relationship: known.relationship,
|
|
80
|
+
scan
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async scanSuiAccountActivity(input) {
|
|
85
|
+
const relationship = input.relationship ?? "affected";
|
|
86
|
+
return this.runActivityScan({
|
|
87
|
+
request: input,
|
|
88
|
+
scanKind: "account_scan",
|
|
89
|
+
relationship,
|
|
90
|
+
cursorInvalidMessage: "Activity scan cursor was rejected by the provider",
|
|
91
|
+
sourceCall: ({ account, limit, cursor, fromCheckpoint, toCheckpoint }) => this.options.source.scanAccount({
|
|
92
|
+
account,
|
|
93
|
+
relationship,
|
|
94
|
+
limit,
|
|
95
|
+
cursor,
|
|
96
|
+
fromCheckpoint,
|
|
97
|
+
toCheckpoint
|
|
98
|
+
})
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async scanSuiFunctionActivity(input) {
|
|
102
|
+
const functionTarget = parseSuiFunctionTarget(input.function);
|
|
103
|
+
return this.runActivityScan({
|
|
104
|
+
request: input,
|
|
105
|
+
scanKind: "function_scan",
|
|
106
|
+
relationship: "sent",
|
|
107
|
+
cursorInvalidMessage: "Function activity scan cursor was rejected by the provider",
|
|
108
|
+
extraResultFields: { function: functionTarget.target },
|
|
109
|
+
sourceCall: ({ account, limit, cursor, fromCheckpoint, toCheckpoint }) => this.options.source.scanFunction({
|
|
110
|
+
functionTarget: functionTarget.target,
|
|
111
|
+
sentAddress: account,
|
|
112
|
+
limit,
|
|
113
|
+
cursor,
|
|
114
|
+
fromCheckpoint,
|
|
115
|
+
toCheckpoint
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
async runActivityScan(input) {
|
|
120
|
+
const limit = normalizeActivityLimit(input.request.limit);
|
|
121
|
+
const fromCheckpoint = normalizeCheckpointBound(input.request.fromCheckpoint, "fromCheckpoint");
|
|
122
|
+
const toCheckpoint = normalizeCheckpointBound(input.request.toCheckpoint, "toCheckpoint");
|
|
123
|
+
assertCheckpointRange(fromCheckpoint, toCheckpoint);
|
|
124
|
+
const fromTimestamp = normalizeTimestampBound(input.request.fromTimestamp, "fromTimestamp");
|
|
125
|
+
const toTimestamp = normalizeTimestampBound(input.request.toTimestamp, "toTimestamp");
|
|
126
|
+
assertTimestampRange(fromTimestamp, toTimestamp);
|
|
127
|
+
const accountScope = input.request.account === undefined
|
|
128
|
+
? await this.resolveActiveAccount()
|
|
129
|
+
: { account: parseAccount(input.request.account), accountSource: "explicit_filter" };
|
|
130
|
+
const knownAccount = await this.options.activityStore.getKnownAccount(accountScope.account);
|
|
131
|
+
const source = await this.verifySource();
|
|
132
|
+
const fetchedAt = this.now().toISOString();
|
|
133
|
+
let page;
|
|
134
|
+
try {
|
|
135
|
+
page = await input.sourceCall({
|
|
136
|
+
account: accountScope.account,
|
|
137
|
+
relationship: input.relationship,
|
|
138
|
+
limit,
|
|
139
|
+
cursor: input.request.cursor,
|
|
140
|
+
fromCheckpoint,
|
|
141
|
+
toCheckpoint
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
if (error instanceof TransactionActivitySourceError && error.reason === "cursor_invalid") {
|
|
146
|
+
throw new TransactionActivityError("input_invalid", input.cursorInvalidMessage, {
|
|
147
|
+
reason: "cursor_invalid"
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
throw this.sourceError(error);
|
|
151
|
+
}
|
|
152
|
+
const orderingVerified = isMonotonicActivityOrder(page.transactions);
|
|
153
|
+
const orderedTransactions = [...page.transactions].sort(compareActivityFactsDescending);
|
|
154
|
+
const orderedPage = { ...page, transactions: orderedTransactions };
|
|
155
|
+
const windowComplete = windowCompletion({
|
|
156
|
+
account: input.request.account,
|
|
157
|
+
relationship: input.relationship,
|
|
158
|
+
limit: input.request.limit,
|
|
159
|
+
cursor: input.request.cursor,
|
|
160
|
+
fromCheckpoint,
|
|
161
|
+
toCheckpoint,
|
|
162
|
+
fromTimestamp,
|
|
163
|
+
toTimestamp
|
|
164
|
+
}, orderedPage, orderingVerified);
|
|
165
|
+
const filteredTransactions = filterTransactionsForRequestedWindow(orderedTransactions, {
|
|
166
|
+
account: accountScope.account,
|
|
167
|
+
relationship: input.relationship,
|
|
168
|
+
fromCheckpoint,
|
|
169
|
+
toCheckpoint,
|
|
170
|
+
fromTimestamp,
|
|
171
|
+
toTimestamp
|
|
172
|
+
});
|
|
173
|
+
const accountScopedTransactions = attachRequestedAccountEffects(filteredTransactions, accountScope.account);
|
|
174
|
+
const cursor = page.hasMore ? page.cursor : undefined;
|
|
175
|
+
const incompleteReason = incompleteReasonForScan({ orderingVerified, windowComplete });
|
|
176
|
+
const resultBase = {
|
|
177
|
+
status: "ok",
|
|
178
|
+
fetchedAt,
|
|
179
|
+
account: accountScope.account,
|
|
180
|
+
accountKnown: knownAccount !== undefined,
|
|
181
|
+
accountSource: accountScope.accountSource,
|
|
182
|
+
...(input.extraResultFields ?? {}),
|
|
183
|
+
relationship: input.relationship,
|
|
184
|
+
requestedAccount: buildRequestedAccountActivity({
|
|
185
|
+
account: accountScope.account,
|
|
186
|
+
relationship: input.relationship,
|
|
187
|
+
transactions: accountScopedTransactions
|
|
188
|
+
}),
|
|
189
|
+
source: { ...source, method: "Query.transactions" },
|
|
190
|
+
transactions: accountScopedTransactions,
|
|
191
|
+
hasMore: page.hasMore,
|
|
192
|
+
...(cursor === undefined ? {} : { continuationCursor: cursor }),
|
|
193
|
+
windowComplete,
|
|
194
|
+
orderingVerified,
|
|
195
|
+
...(incompleteReason === undefined ? {} : { incompleteReason })
|
|
196
|
+
};
|
|
197
|
+
if (!knownAccount) {
|
|
198
|
+
return {
|
|
199
|
+
...resultBase,
|
|
200
|
+
persistence: { stored: false, reason: "account_not_known" }
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
const storageTransactions = accountScopedTransactions.filter((transaction) => transactionMatchesKnownStorageAccount(transaction, knownAccount.address, input.relationship));
|
|
204
|
+
const scan = await this.options.activityStore.recordExternalActivityScan({
|
|
205
|
+
scanId: this.scanId(),
|
|
206
|
+
kind: input.scanKind,
|
|
207
|
+
account: knownAccount.address,
|
|
208
|
+
relationship: input.relationship,
|
|
209
|
+
fromCheckpoint,
|
|
210
|
+
toCheckpoint,
|
|
211
|
+
fromTimestamp,
|
|
212
|
+
toTimestamp,
|
|
213
|
+
limit,
|
|
214
|
+
requestCursor: input.request.cursor,
|
|
215
|
+
responseCursor: cursor,
|
|
216
|
+
endpointHost: source.endpointHost,
|
|
217
|
+
chainIdentifier: source.chainIdentifier,
|
|
218
|
+
fetchedAt,
|
|
219
|
+
hasMore: page.hasMore,
|
|
220
|
+
windowComplete,
|
|
221
|
+
incompleteReason,
|
|
222
|
+
skippedCount: page.transactions.length - storageTransactions.length,
|
|
223
|
+
transactions: await Promise.all(storageTransactions.map((transaction) => this.transactionInputForKnownAccount(transaction, input.relationship, knownAccount.address)))
|
|
224
|
+
});
|
|
225
|
+
return {
|
|
226
|
+
...resultBase,
|
|
227
|
+
persistence: { stored: true, scan }
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
async summarizeSuiAccountActivity(filter) {
|
|
231
|
+
const summary = await this.options.activityStore.summarizeExternalActivity({
|
|
232
|
+
...filter,
|
|
233
|
+
limit: filter.limit ?? REVIEW_ACTIVITY_LIST_DEFAULT_LIMIT
|
|
234
|
+
});
|
|
235
|
+
return {
|
|
236
|
+
...summary,
|
|
237
|
+
status: "ok",
|
|
238
|
+
analysis: buildSuiActivityAnalysis(summary.transactions, {
|
|
239
|
+
truncated: summary.truncated,
|
|
240
|
+
summary: summary.summary
|
|
241
|
+
})
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
async summarizeSuiActivityScan(input) {
|
|
245
|
+
const result = await this.scanSuiAccountActivity(input);
|
|
246
|
+
return {
|
|
247
|
+
...result,
|
|
248
|
+
analysis: buildSuiActivityAnalysis(result.transactions.map((transaction) => ({
|
|
249
|
+
...transaction,
|
|
250
|
+
relationship: result.relationship
|
|
251
|
+
})), {
|
|
252
|
+
relationship: result.relationship,
|
|
253
|
+
windowComplete: result.windowComplete,
|
|
254
|
+
orderingVerified: result.orderingVerified
|
|
255
|
+
})
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
async summarizeSuiFunctionActivityScan(input) {
|
|
259
|
+
const result = await this.scanSuiFunctionActivity(input);
|
|
260
|
+
return {
|
|
261
|
+
...result,
|
|
262
|
+
analysis: buildSuiActivityAnalysis(result.transactions.map((transaction) => ({
|
|
263
|
+
...transaction,
|
|
264
|
+
relationship: result.relationship
|
|
265
|
+
})), {
|
|
266
|
+
relationship: result.relationship,
|
|
267
|
+
windowComplete: result.windowComplete,
|
|
268
|
+
orderingVerified: result.orderingVerified
|
|
269
|
+
})
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
async verifySource() {
|
|
273
|
+
try {
|
|
274
|
+
return await this.options.source.verifyMainnet();
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
throw this.sourceError(error);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
async resolveActiveAccount() {
|
|
281
|
+
const active = await this.options.activityStore.getActiveAccount();
|
|
282
|
+
if (!active) {
|
|
283
|
+
throw new TransactionActivityError("active_account_not_set", "Active account read context is not set", {
|
|
284
|
+
action: "connect_wallet_identity"
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
return { account: active.address, accountSource: "active_account_context" };
|
|
288
|
+
}
|
|
289
|
+
async knownDigestAccountForStorage(explicitAccount, transaction) {
|
|
290
|
+
const sender = transaction.sender === undefined ? undefined : parseSuiAddress(transaction.sender);
|
|
291
|
+
if (explicitAccount !== undefined) {
|
|
292
|
+
const account = await this.options.activityStore.getKnownAccount(explicitAccount);
|
|
293
|
+
if (!account) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
if (explicitAccount === sender) {
|
|
297
|
+
return { account, relationship: "sent" };
|
|
298
|
+
}
|
|
299
|
+
return externalActivityTransactionTouchesAccount(transaction, explicitAccount) ? { account, relationship: "affected" } : undefined;
|
|
300
|
+
}
|
|
301
|
+
const active = await this.options.activityStore.getActiveAccount();
|
|
302
|
+
if (active && active.address === sender) {
|
|
303
|
+
const account = await this.options.activityStore.getKnownAccount(active.address);
|
|
304
|
+
return account === undefined ? undefined : { account, relationship: "sent" };
|
|
305
|
+
}
|
|
306
|
+
if (active && externalActivityTransactionTouchesAccount(transaction, active.address)) {
|
|
307
|
+
const account = await this.options.activityStore.getKnownAccount(active.address);
|
|
308
|
+
return account === undefined ? undefined : { account, relationship: "affected" };
|
|
309
|
+
}
|
|
310
|
+
if (sender !== undefined) {
|
|
311
|
+
const senderAccount = await this.options.activityStore.getKnownAccount(sender);
|
|
312
|
+
if (senderAccount) {
|
|
313
|
+
return { account: senderAccount, relationship: "sent" };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
for (const owner of externalActivityTransactionBalanceOwners(transaction)) {
|
|
317
|
+
const account = await this.options.activityStore.getKnownAccount(owner);
|
|
318
|
+
if (account) {
|
|
319
|
+
return { account, relationship: "affected" };
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
async transactionInputForKnownAccount(transaction, relationship, storageAccount) {
|
|
325
|
+
const sender = transaction.sender ? await this.options.activityStore.getKnownAccount(transaction.sender) : undefined;
|
|
326
|
+
return {
|
|
327
|
+
digest: transaction.digest,
|
|
328
|
+
relationship,
|
|
329
|
+
checkpoint: transaction.checkpoint,
|
|
330
|
+
timestamp: transaction.timestamp,
|
|
331
|
+
status: transaction.status,
|
|
332
|
+
knownSenderAccountId: sender?.id,
|
|
333
|
+
details: transaction.details === undefined
|
|
334
|
+
? undefined
|
|
335
|
+
: sanitizeExternalActivityTransactionDetailsForKnownAccount(transaction.details, storageAccount)
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
async mapSourceCall(call) {
|
|
339
|
+
try {
|
|
340
|
+
return await call();
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
throw this.sourceError(error);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
sourceError(error) {
|
|
347
|
+
if (error instanceof TransactionActivityError) {
|
|
348
|
+
return error;
|
|
349
|
+
}
|
|
350
|
+
if (error instanceof TransactionActivitySourceError) {
|
|
351
|
+
return new TransactionActivityError("internal_error", "Sui GraphQL activity source failed", {
|
|
352
|
+
reason: error.reason,
|
|
353
|
+
...error.details
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
if (error instanceof SuiEndpointError && error.kind === "chain_identifier_mismatch") {
|
|
357
|
+
return new TransactionActivityError("network_mismatch", "Sui GraphQL endpoint is not mainnet", {
|
|
358
|
+
reason: "chain_identifier_mismatch"
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
return new TransactionActivityError("internal_error", "Sui GraphQL activity source failed", {
|
|
362
|
+
message: error instanceof Error ? error.message : String(error)
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function parseAccount(value) {
|
|
367
|
+
const normalized = parseSuiAddress(value);
|
|
368
|
+
if (!normalized) {
|
|
369
|
+
throw new TransactionActivityError("input_invalid", "Invalid Sui account address", { field: "account" });
|
|
370
|
+
}
|
|
371
|
+
return normalized;
|
|
372
|
+
}
|
|
373
|
+
function parseTransactionDigest(value) {
|
|
374
|
+
const trimmed = value.trim();
|
|
375
|
+
if (!isValidTransactionDigest(trimmed)) {
|
|
376
|
+
throw new TransactionActivityError("input_invalid", "Invalid Sui transaction digest", { field: "digest" });
|
|
377
|
+
}
|
|
378
|
+
return trimmed;
|
|
379
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export class TransactionActivityError extends Error {
|
|
2
|
+
kind;
|
|
3
|
+
details;
|
|
4
|
+
constructor(kind, message, details = {}) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.kind = kind;
|
|
7
|
+
this.details = details;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class TransactionActivitySourceError extends Error {
|
|
11
|
+
reason;
|
|
12
|
+
details;
|
|
13
|
+
constructor(reason, message, details = {}) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.reason = reason;
|
|
16
|
+
this.details = details;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { appendFile } from "node:fs/promises";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
export class NullEventLogSink {
|
|
4
|
+
async append(_record) { }
|
|
5
|
+
}
|
|
6
|
+
export class NdjsonEventLogSink {
|
|
7
|
+
filePath;
|
|
8
|
+
constructor(filePath) {
|
|
9
|
+
this.filePath = filePath;
|
|
10
|
+
}
|
|
11
|
+
async append(record) {
|
|
12
|
+
await appendFile(this.filePath, `${JSON.stringify(redactEvent(record))}\n`, "utf8");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function redactEvent(record) {
|
|
16
|
+
const redacted = {
|
|
17
|
+
type: record.type,
|
|
18
|
+
sessionId: record.sessionId,
|
|
19
|
+
at: record.at
|
|
20
|
+
};
|
|
21
|
+
if (record.planId)
|
|
22
|
+
redacted.planId = record.planId;
|
|
23
|
+
if (record.walletAddressHash)
|
|
24
|
+
redacted.walletAddressHash = record.walletAddressHash;
|
|
25
|
+
if (record.txDigest)
|
|
26
|
+
redacted.txDigest = record.txDigest;
|
|
27
|
+
if (record.status)
|
|
28
|
+
redacted.status = record.status;
|
|
29
|
+
if (record.reason)
|
|
30
|
+
redacted.reason = record.reason;
|
|
31
|
+
return redacted;
|
|
32
|
+
}
|
|
33
|
+
export function hashEventValue(value) {
|
|
34
|
+
return `sha256:${createHash("sha256").update(value).digest("hex")}`;
|
|
35
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { formatRawAmount, normalizeCoinType } from "../read/coinMetadata.js";
|
|
2
|
+
import { listDeepbookTokenRegistry } from "../read/deepbookRegistry.js";
|
|
3
|
+
import { SUI_USD_SETTLEMENT_ASSET_GROUP_ID } from "../read/readServiceTypes.js";
|
|
4
|
+
const USD_SETTLEMENT_SYMBOLS = new Set(["USDC", "USDT", "WUSDC", "WUSDT", "AUSD", "USDSUI", "SUIUSDE"]);
|
|
5
|
+
export const SUI_USD_SETTLEMENT_ASSETS_ALIASES = [
|
|
6
|
+
"dollar",
|
|
7
|
+
"dollars",
|
|
8
|
+
"usd",
|
|
9
|
+
"usd-like",
|
|
10
|
+
"stablecoin",
|
|
11
|
+
"stablecoins"
|
|
12
|
+
];
|
|
13
|
+
export function normalizeSettlementDenomination(denomination) {
|
|
14
|
+
const normalized = denomination.trim().toLowerCase();
|
|
15
|
+
if (normalized === "달러") {
|
|
16
|
+
return "dollar";
|
|
17
|
+
}
|
|
18
|
+
if (SUI_USD_SETTLEMENT_ASSETS_ALIASES.includes(normalized)) {
|
|
19
|
+
return normalized;
|
|
20
|
+
}
|
|
21
|
+
throw new Error("Unsupported settlement denomination");
|
|
22
|
+
}
|
|
23
|
+
export function buildUsdSettlementAssetGroup(coins) {
|
|
24
|
+
const registry = listDeepbookTokenRegistry(coins);
|
|
25
|
+
const includedAssets = [];
|
|
26
|
+
const excludedAssets = [];
|
|
27
|
+
for (const token of registry) {
|
|
28
|
+
const coinType = normalizeCoinType(token.type);
|
|
29
|
+
if (USD_SETTLEMENT_SYMBOLS.has(token.symbol)) {
|
|
30
|
+
includedAssets.push({
|
|
31
|
+
symbol: token.symbol,
|
|
32
|
+
coinType,
|
|
33
|
+
decimals: token.decimals,
|
|
34
|
+
unitSource: token.unitSource,
|
|
35
|
+
poolKeys: [...token.poolKeys]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
excludedAssets.push({
|
|
40
|
+
symbol: token.symbol,
|
|
41
|
+
coinType,
|
|
42
|
+
reason: excludedSettlementAssetReason(token.symbol)
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
includedAssets.sort((left, right) => left.symbol.localeCompare(right.symbol));
|
|
47
|
+
excludedAssets.sort((left, right) => left.symbol.localeCompare(right.symbol));
|
|
48
|
+
return {
|
|
49
|
+
id: SUI_USD_SETTLEMENT_ASSET_GROUP_ID,
|
|
50
|
+
label: "Sui USD-denominated settlement assets",
|
|
51
|
+
aliases: [...SUI_USD_SETTLEMENT_ASSETS_ALIASES],
|
|
52
|
+
includedAssets,
|
|
53
|
+
excludedAssets,
|
|
54
|
+
evidenceSources: {
|
|
55
|
+
sdk: "@mysten/deepbook-v3",
|
|
56
|
+
registry: ["mainnetCoins", "mainnetPools"],
|
|
57
|
+
network: "mainnet",
|
|
58
|
+
unitSource: "deepbook_mainnetCoins_scalar"
|
|
59
|
+
},
|
|
60
|
+
limitations: [
|
|
61
|
+
"static_pinned_sdk_registry_not_live_liquidity",
|
|
62
|
+
"not_fiat_usd_cash_out",
|
|
63
|
+
"not_payment_execution",
|
|
64
|
+
"not_route_recommendation",
|
|
65
|
+
"not_signing_readiness"
|
|
66
|
+
]
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function commonAssetGroupDecimals(assets) {
|
|
70
|
+
const decimals = new Set(assets.map((asset) => asset.decimals));
|
|
71
|
+
return decimals.size === 1 ? assets[0]?.decimals : undefined;
|
|
72
|
+
}
|
|
73
|
+
export function formatSettlementAssetRawAmount(rawAmount, decimals) {
|
|
74
|
+
return formatRawAmount(rawAmount, decimals);
|
|
75
|
+
}
|
|
76
|
+
function excludedSettlementAssetReason(symbol) {
|
|
77
|
+
if (symbol === "DEEP") {
|
|
78
|
+
return "protocol_fee_asset";
|
|
79
|
+
}
|
|
80
|
+
if (symbol === "SUI") {
|
|
81
|
+
return "gas_or_volatile_asset";
|
|
82
|
+
}
|
|
83
|
+
if (["BETH", "LZWBTC", "WETH", "WBTC", "XBTC"].includes(symbol)) {
|
|
84
|
+
return "volatile_or_non_usd_asset";
|
|
85
|
+
}
|
|
86
|
+
return "not_in_usd_settlement_asset_group";
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const MAX_RAW_U64 = (1n << 64n) - 1n;
|
|
3
|
+
const CANONICAL_UNSIGNED_INTEGER_PATTERN = /^(?:0|[1-9][0-9]*)$/;
|
|
4
|
+
const SIGNED_RAW_INTEGER_PATTERN = /^(?:0|-?[1-9][0-9]*)$/;
|
|
5
|
+
export function parseRawU64(value, field, options = {}) {
|
|
6
|
+
if (!/^\d+$/.test(value)) {
|
|
7
|
+
throw new Error(`${field} must be an unsigned integer string`);
|
|
8
|
+
}
|
|
9
|
+
const amount = BigInt(value);
|
|
10
|
+
if (options.positive && amount === 0n) {
|
|
11
|
+
throw new Error(`${field} must be positive`);
|
|
12
|
+
}
|
|
13
|
+
if (amount > MAX_RAW_U64) {
|
|
14
|
+
throw new Error(`${field} must fit u64`);
|
|
15
|
+
}
|
|
16
|
+
return amount;
|
|
17
|
+
}
|
|
18
|
+
export function makeRawU64StringSchema(field) {
|
|
19
|
+
const label = field === "rawAmount" ? "amount" : field;
|
|
20
|
+
return z.string().min(1).refine((value) => {
|
|
21
|
+
try {
|
|
22
|
+
parseRawU64(value, field);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}, `Expected a raw u64 ${label} string`);
|
|
29
|
+
}
|
|
30
|
+
export function parseCanonicalRawU64(value, field, options = {}) {
|
|
31
|
+
if (!CANONICAL_UNSIGNED_INTEGER_PATTERN.test(value)) {
|
|
32
|
+
throw new Error(`${field} must be a canonical unsigned integer string`);
|
|
33
|
+
}
|
|
34
|
+
return parseRawU64(value, field, options);
|
|
35
|
+
}
|
|
36
|
+
export function makeCanonicalRawU64StringSchema(field) {
|
|
37
|
+
return z.string().min(1).refine((value) => {
|
|
38
|
+
try {
|
|
39
|
+
parseCanonicalRawU64(value, field);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}, "Expected an unsigned integer string");
|
|
46
|
+
}
|
|
47
|
+
export function parseSignedRawInteger(value, field) {
|
|
48
|
+
if (!SIGNED_RAW_INTEGER_PATTERN.test(value)) {
|
|
49
|
+
throw new Error(`${field} must be a signed integer string`);
|
|
50
|
+
}
|
|
51
|
+
return BigInt(value);
|
|
52
|
+
}
|
|
53
|
+
export function makeSignedRawIntegerStringSchema(field) {
|
|
54
|
+
return z.string().min(1).refine((value) => {
|
|
55
|
+
try {
|
|
56
|
+
parseSignedRawInteger(value, field);
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}, "Expected a signed integer string");
|
|
63
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const LOCAL_SETTING_KEYS = ["suiGrpcUrl", "suiGraphqlUrl"];
|
|
2
|
+
export const SETTINGS_APPLIES_AFTER_RESTART = "mcp_server_restart";
|
|
3
|
+
export class PreferencesStoreError extends Error {
|
|
4
|
+
kind;
|
|
5
|
+
details;
|
|
6
|
+
constructor(kind, message, details = {}) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.kind = kind;
|
|
9
|
+
this.details = details;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class LocalSettingsError extends Error {
|
|
13
|
+
kind;
|
|
14
|
+
details;
|
|
15
|
+
constructor(kind, message, details = {}) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.kind = kind;
|
|
18
|
+
this.details = details;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function assertLocalSettingKey(key) {
|
|
22
|
+
if (key === "suiGrpcUrl" || key === "suiGraphqlUrl") {
|
|
23
|
+
return key;
|
|
24
|
+
}
|
|
25
|
+
throw new PreferencesStoreError("unknown_key", "Unknown local setting key", { key });
|
|
26
|
+
}
|