@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,117 @@
|
|
|
1
|
+
import { AggregatorQuoter, Protocol } from "@flowx-finance/sdk";
|
|
2
|
+
import { ReadServiceInputError } from "./readServiceTypes.js";
|
|
3
|
+
/**
|
|
4
|
+
* Thin wrapper around the FlowX aggregator quoter, restricted to FlowX CLMM
|
|
5
|
+
* single-hop routes. Normalizes the response into plain data so the read
|
|
6
|
+
* service can validate it against the pinned registry, and so tests can
|
|
7
|
+
* inject fakes without the SDK.
|
|
8
|
+
*/
|
|
9
|
+
const FLOWX_QUOTER_MAX_HOPS = 1;
|
|
10
|
+
export function createFlowxQuoteClient() {
|
|
11
|
+
const quoter = new AggregatorQuoter("mainnet");
|
|
12
|
+
return {
|
|
13
|
+
async getSwapRoutes(request) {
|
|
14
|
+
let result;
|
|
15
|
+
try {
|
|
16
|
+
result = await quoter.getRoutes({
|
|
17
|
+
tokenIn: request.tokenInType,
|
|
18
|
+
tokenOut: request.tokenOutType,
|
|
19
|
+
amountIn: request.amountInRaw,
|
|
20
|
+
includeSources: [Protocol.FLOWX_V3],
|
|
21
|
+
maxHops: FLOWX_QUOTER_MAX_HOPS
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter request failed", {
|
|
26
|
+
reason: error instanceof Error ? error.message : "unknown"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return normalizeFlowxQuoterResult(result);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Build-grade quote source for the FlowX review adapter: one quoter response
|
|
35
|
+
* yields both the normalized quote (validated against the pinned registry)
|
|
36
|
+
* and the SDK route entities the local transaction build consumes.
|
|
37
|
+
*/
|
|
38
|
+
export function createFlowxSwapReviewQuoteSource(options) {
|
|
39
|
+
const quoter = new AggregatorQuoter("mainnet");
|
|
40
|
+
const now = options?.now ?? (() => new Date());
|
|
41
|
+
return {
|
|
42
|
+
async getSwapRoutesForBuild(request) {
|
|
43
|
+
let result;
|
|
44
|
+
try {
|
|
45
|
+
result = await quoter.getRoutes({
|
|
46
|
+
tokenIn: request.tokenInType,
|
|
47
|
+
tokenOut: request.tokenOutType,
|
|
48
|
+
amountIn: request.amountInRaw,
|
|
49
|
+
includeSources: [Protocol.FLOWX_V3],
|
|
50
|
+
maxHops: FLOWX_QUOTER_MAX_HOPS
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter request failed", {
|
|
55
|
+
reason: error instanceof Error ? error.message : "unknown"
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
normalized: normalizeFlowxQuoterResult(result),
|
|
60
|
+
sdkRoutes: result.routes,
|
|
61
|
+
fetchedAt: now().toISOString()
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function normalizeFlowxQuoterResult(result) {
|
|
67
|
+
const rawQuote = result.rawQuote;
|
|
68
|
+
if (!rawQuote || !Array.isArray(rawQuote.paths)) {
|
|
69
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter response is missing raw route paths", {
|
|
70
|
+
hasRawQuote: rawQuote !== undefined
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const amountInRaw = stringifyAmount(result.amountIn, "amountIn");
|
|
74
|
+
const amountOutRaw = stringifyAmount(result.amountOut, "amountOut");
|
|
75
|
+
const paths = rawQuote.paths.flat().map((path, index) => {
|
|
76
|
+
if (typeof path.poolId !== "string" || path.poolId.length === 0) {
|
|
77
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter path is missing a pool id", { index });
|
|
78
|
+
}
|
|
79
|
+
if (typeof path.source !== "string" || path.source.length === 0) {
|
|
80
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter path is missing a source label", { index });
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
poolId: path.poolId,
|
|
84
|
+
source: path.source,
|
|
85
|
+
swapXToY: typeof path.extra?.swapXToY === "boolean" ? path.extra.swapXToY : undefined,
|
|
86
|
+
feeRate: typeof path.extra?.fee === "number" ? path.extra.fee : undefined
|
|
87
|
+
};
|
|
88
|
+
});
|
|
89
|
+
if (paths.length === 0) {
|
|
90
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter returned no route paths", {});
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
amountInRaw,
|
|
94
|
+
amountOutRaw,
|
|
95
|
+
paths,
|
|
96
|
+
protocolConfig: normalizeProtocolConfig(rawQuote.protocolConfig)
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function normalizeProtocolConfig(config) {
|
|
100
|
+
const clmm = config?.flowx_clmm;
|
|
101
|
+
if (typeof clmm !== "object" || clmm === null) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const record = clmm;
|
|
105
|
+
return {
|
|
106
|
+
poolRegistryObjectId: typeof record.poolRegistryObjectId === "string" ? record.poolRegistryObjectId : undefined,
|
|
107
|
+
versionedObjectId: typeof record.versionedObjectId === "string" ? record.versionedObjectId : undefined,
|
|
108
|
+
wrappedRouterPackageId: typeof record.wrappedRouterPackageId === "string" ? record.wrappedRouterPackageId : undefined
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
function stringifyAmount(value, field) {
|
|
112
|
+
const text = typeof value === "string" ? value : value?.toString();
|
|
113
|
+
if (text === undefined || !/^\d+$/.test(text)) {
|
|
114
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter amount is not a raw integer", { field });
|
|
115
|
+
}
|
|
116
|
+
return text;
|
|
117
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { FLOWX_CLMM_MAINNET, getFlowxPoolById } from "./flowxRegistry.js";
|
|
2
|
+
import { FLOWX_SWAP_QUOTE_QUANTITY_KIND, ReadServiceInputError } from "./readServiceTypes.js";
|
|
3
|
+
export function flowxQuoteQuantitySemantics() {
|
|
4
|
+
return {
|
|
5
|
+
kind: FLOWX_SWAP_QUOTE_QUANTITY_KIND,
|
|
6
|
+
inputAmountKind: "display_source_amount_converted_to_raw",
|
|
7
|
+
allowedUse: "indicative_flowx_route_quote",
|
|
8
|
+
rawAmountAvailable: true,
|
|
9
|
+
rawEvidenceField: "routeEvidence",
|
|
10
|
+
chainVerified: false,
|
|
11
|
+
paymentCoverageAvailable: false,
|
|
12
|
+
shortfallContributionAvailable: false,
|
|
13
|
+
routeDependentPaymentSupportAvailable: false,
|
|
14
|
+
requiresIntentEvidenceForCoverage: true,
|
|
15
|
+
canUseForPaymentAnswer: false,
|
|
16
|
+
canUseForShortfallAnswer: false,
|
|
17
|
+
doNotCombineWithPaymentAnswer: true,
|
|
18
|
+
requiredPaymentAnswerTool: "read.preview_intent_evidence",
|
|
19
|
+
paymentAnswerUseBlockedReason: "quote_output_is_price_reference_not_payment_answer",
|
|
20
|
+
requiredPaymentAnswerField: "responseSummary",
|
|
21
|
+
fiatUsdCashOutAvailable: false,
|
|
22
|
+
externalMarketPriceConversionAvailable: false,
|
|
23
|
+
externalMarketLookupAvailable: false,
|
|
24
|
+
usdPegAssumptionAvailable: false,
|
|
25
|
+
bankCashOutEstimateAvailable: false,
|
|
26
|
+
profitAndLossAvailable: false,
|
|
27
|
+
costBasisAvailable: false,
|
|
28
|
+
priceImpactAvailable: false,
|
|
29
|
+
midPriceSlippageAvailable: false,
|
|
30
|
+
venueComparisonAvailable: false,
|
|
31
|
+
routeRecommendationAvailable: false,
|
|
32
|
+
notFor: [
|
|
33
|
+
"signing",
|
|
34
|
+
"funding",
|
|
35
|
+
"payment_coverage",
|
|
36
|
+
"shortfall_contribution",
|
|
37
|
+
"route_dependent_payment_support",
|
|
38
|
+
"route_liquidity",
|
|
39
|
+
"min_out",
|
|
40
|
+
"liquidity_verdict",
|
|
41
|
+
"price_impact",
|
|
42
|
+
"mid_price_slippage",
|
|
43
|
+
"quote_vs_mid_slippage",
|
|
44
|
+
"effective_price",
|
|
45
|
+
"venue_comparison",
|
|
46
|
+
"best_route",
|
|
47
|
+
"route_recommendation",
|
|
48
|
+
"transaction_building",
|
|
49
|
+
"fiat_usd_cash_out",
|
|
50
|
+
"external_market_price_conversion",
|
|
51
|
+
"external_market_lookup",
|
|
52
|
+
"usd_peg_assumption",
|
|
53
|
+
"bank_cash_out_estimate",
|
|
54
|
+
"profit_or_pnl",
|
|
55
|
+
"cost_basis"
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validate a normalized FlowX quoter response against the pinned registry and
|
|
61
|
+
* the requested pair. Every check fails closed: an unknown pool, a foreign
|
|
62
|
+
* route source, a multi-hop path, an amount echo mismatch, or a drifted
|
|
63
|
+
* protocol config pin stops the quote instead of being silently accepted.
|
|
64
|
+
*/
|
|
65
|
+
export function validateFlowxRouteQuote(input) {
|
|
66
|
+
const { pair, quote } = input;
|
|
67
|
+
if (quote.amountInRaw !== input.requestedAmountInRaw) {
|
|
68
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter echoed a different input amount", {
|
|
69
|
+
requested: input.requestedAmountInRaw,
|
|
70
|
+
echoed: quote.amountInRaw
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const pools = [];
|
|
74
|
+
for (const path of quote.paths) {
|
|
75
|
+
if (path.source !== FLOWX_CLMM_MAINNET.quoterSource) {
|
|
76
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX route includes a non-FlowX-CLMM source", {
|
|
77
|
+
poolId: path.poolId,
|
|
78
|
+
source: path.source
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const pinned = getFlowxPoolById(path.poolId);
|
|
82
|
+
if (!pinned) {
|
|
83
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX route uses a pool that is not in the pinned registry", {
|
|
84
|
+
poolId: path.poolId,
|
|
85
|
+
action: "regenerate_flowx_registry"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (path.swapXToY !== undefined && path.swapXToY !== pair.swapXToY) {
|
|
89
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX route direction disagrees with the pinned pair orientation", {
|
|
90
|
+
poolId: path.poolId,
|
|
91
|
+
routeSwapXToY: path.swapXToY,
|
|
92
|
+
pinnedSwapXToY: pair.swapXToY
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (path.feeRate !== undefined && path.feeRate !== pinned.feeRate) {
|
|
96
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX route fee disagrees with the pinned pool fee", {
|
|
97
|
+
poolId: path.poolId,
|
|
98
|
+
routeFeeRate: path.feeRate,
|
|
99
|
+
pinnedFeeRate: pinned.feeRate
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
pools.push({
|
|
103
|
+
poolKey: pinned.poolKey,
|
|
104
|
+
poolId: pinned.poolId,
|
|
105
|
+
feeRate: pinned.feeRate,
|
|
106
|
+
tickSpacing: pinned.tickSpacing,
|
|
107
|
+
swapXToY: pair.swapXToY
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (pools.length !== 1) {
|
|
111
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX route is not a single-hop path", {
|
|
112
|
+
hopCount: pools.length
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const config = quote.protocolConfig;
|
|
116
|
+
if (!config) {
|
|
117
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX quoter response did not carry the protocol config pin", {});
|
|
118
|
+
}
|
|
119
|
+
const pinDrift = {};
|
|
120
|
+
if (config.poolRegistryObjectId !== FLOWX_CLMM_MAINNET.poolRegistry.objectId) {
|
|
121
|
+
pinDrift.poolRegistryObjectId = {
|
|
122
|
+
pinned: FLOWX_CLMM_MAINNET.poolRegistry.objectId,
|
|
123
|
+
observed: config.poolRegistryObjectId
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (config.versionedObjectId !== FLOWX_CLMM_MAINNET.versioned.objectId) {
|
|
127
|
+
pinDrift.versionedObjectId = {
|
|
128
|
+
pinned: FLOWX_CLMM_MAINNET.versioned.objectId,
|
|
129
|
+
observed: config.versionedObjectId
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (config.wrappedRouterPackageId !== FLOWX_CLMM_MAINNET.universalRouter.wrappedRouterPackageId) {
|
|
133
|
+
pinDrift.wrappedRouterPackageId = {
|
|
134
|
+
pinned: FLOWX_CLMM_MAINNET.universalRouter.wrappedRouterPackageId,
|
|
135
|
+
observed: config.wrappedRouterPackageId
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
if (Object.keys(pinDrift).length > 0) {
|
|
139
|
+
throw new ReadServiceInputError("quote_unavailable", "FlowX protocol config drifted from the pinned registry", {
|
|
140
|
+
pinDrift,
|
|
141
|
+
action: "regenerate_flowx_registry"
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return { pools };
|
|
145
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { normalizeCoinType } from "./coinMetadata.js";
|
|
2
|
+
import { ReadServiceInputError } from "./readServiceTypes.js";
|
|
3
|
+
/**
|
|
4
|
+
* Pinned FlowX CLMM mainnet registry.
|
|
5
|
+
*
|
|
6
|
+
* Values were read from Sui mainnet directly (package introspection, the
|
|
7
|
+
* shared PoolRegistry object, and its dynamic fields) on 2026-06-12 and
|
|
8
|
+
* cross-checked against @flowx-finance/sdk@2.1.0 CONFIGS and a live quoter
|
|
9
|
+
* response. `scripts/generate-flowx-registry.ts` re-verifies every value
|
|
10
|
+
* against the chain and fails loudly on drift; it never rewrites this module.
|
|
11
|
+
*
|
|
12
|
+
* Static known metadata only - not live liquidity, balances, quotes, or
|
|
13
|
+
* final execution truth.
|
|
14
|
+
*/
|
|
15
|
+
export const FLOWX_CLMM_PROTOCOL_ID = "flowx-clmm";
|
|
16
|
+
export const FLOWX_CLMM_UNIT_SOURCE = "flowx_pinned_registry";
|
|
17
|
+
export const FLOWX_CLMM_MAINNET = {
|
|
18
|
+
/** Current package storage id (upgrade version 7 at probe time). */
|
|
19
|
+
currentPackageId: "0xde2c47eb0da8c74e4d0f6a220c41619681221b9c2590518095f0f0c2d3f3c772",
|
|
20
|
+
/** Original publish id - all on-chain struct types use this address. */
|
|
21
|
+
originalPackageId: "0x25929e7f29e0a30eb4e692952ba1b5b65a3a4d65ab5f2a32e1ba3edcb587f26d",
|
|
22
|
+
poolRegistry: {
|
|
23
|
+
objectId: "0x27565d24a4cd51127ac90e4074a841bbe356cca7bf5759ddc14a975be1632abc",
|
|
24
|
+
initialSharedVersion: "101644053",
|
|
25
|
+
type: "0x25929e7f29e0a30eb4e692952ba1b5b65a3a4d65ab5f2a32e1ba3edcb587f26d::pool_manager::PoolRegistry"
|
|
26
|
+
},
|
|
27
|
+
versioned: {
|
|
28
|
+
objectId: "0x67624a1533b5aff5d0dfcf5e598684350efd38134d2d245f475524c03a64e656",
|
|
29
|
+
initialSharedVersion: "101644053",
|
|
30
|
+
type: "0x25929e7f29e0a30eb4e692952ba1b5b65a3a4d65ab5f2a32e1ba3edcb587f26d::versioned::Versioned"
|
|
31
|
+
},
|
|
32
|
+
/**
|
|
33
|
+
* Universal-router surfaces used by the SDK-built swap transaction. The
|
|
34
|
+
* wrappedRouterPackageId is delivered inside quoter API responses, so the
|
|
35
|
+
* quote path re-checks it against this pin on every quote.
|
|
36
|
+
*/
|
|
37
|
+
universalRouter: {
|
|
38
|
+
packageId: "0xc263060d3cbb4155057f0010f92f63ca56d5121c298d01f7a33607342ec299b0",
|
|
39
|
+
treasuryObjectId: "0x25db8128dc9ccbe5fcd15e5700fea555c6b111a8c8a1f20c426b696caac2bea4",
|
|
40
|
+
tradeIdTrackerObjectId: "0x9ab469842f85fd2a1bac9ba695d867adb1caa7d5705809737922b5cee552eb6f",
|
|
41
|
+
partnerRegistryObjectId: "0x29e6c1c2176485dc045a2e39eb8844b4ca1cf8452d964447c11202f84a76cb1a",
|
|
42
|
+
versionedObjectId: "0xada98dd9e028db64e206dd81fdecb3dbc8b4c16be08d9f175550032bfdcf56f3",
|
|
43
|
+
wrappedRouterPackageId: "0x1d200e5a0709f84736d1ec06a5e9a961f4fa86f2d43d15e3a0441ae152440ede"
|
|
44
|
+
},
|
|
45
|
+
/** Aggregator quoter source label for FlowX CLMM routes. */
|
|
46
|
+
quoterSource: "FLOWX_CLMM",
|
|
47
|
+
/** Pool fee rates use a 1_000_000 denominator (e.g. 3000 = 0.3%). */
|
|
48
|
+
feeRateDenominator: 1_000_000
|
|
49
|
+
};
|
|
50
|
+
export const FLOWX_PINNED_COINS = {
|
|
51
|
+
SUI: {
|
|
52
|
+
symbol: "SUI",
|
|
53
|
+
coinType: "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI",
|
|
54
|
+
decimals: 9
|
|
55
|
+
},
|
|
56
|
+
USDC: {
|
|
57
|
+
symbol: "USDC",
|
|
58
|
+
coinType: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
|
|
59
|
+
decimals: 6
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
function suiUsdcPool(poolId, feeRate, tickSpacing) {
|
|
63
|
+
return {
|
|
64
|
+
poolKey: `SUI_USDC_${feeRate}`,
|
|
65
|
+
poolId,
|
|
66
|
+
symbolX: FLOWX_PINNED_COINS.SUI.symbol,
|
|
67
|
+
symbolY: FLOWX_PINNED_COINS.USDC.symbol,
|
|
68
|
+
coinTypeX: FLOWX_PINNED_COINS.SUI.coinType,
|
|
69
|
+
coinTypeY: FLOWX_PINNED_COINS.USDC.coinType,
|
|
70
|
+
decimalsX: FLOWX_PINNED_COINS.SUI.decimals,
|
|
71
|
+
decimalsY: FLOWX_PINNED_COINS.USDC.decimals,
|
|
72
|
+
feeRate,
|
|
73
|
+
tickSpacing,
|
|
74
|
+
unitSource: FLOWX_CLMM_UNIT_SOURCE
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Every SUI/USDC pool discovered by direct PoolRegistry dynamic-field reads
|
|
79
|
+
* (2026-06-12, 1189 pools total). One pool exists per fee tier; the registry
|
|
80
|
+
* lists all of them without ranking - pool selection is never advice here.
|
|
81
|
+
*/
|
|
82
|
+
export const FLOWX_PINNED_POOLS = [
|
|
83
|
+
suiUsdcPool("0xf143ac1cc2c012e31df55f21a5d9f406adc8f1ac08d014f84475a3b21953dd37", 10, 1),
|
|
84
|
+
suiUsdcPool("0x9c1cc6fc3c0060b9544dcaba50c9564706a558ef7e089895e86fbca1851c3d43", 100, 2),
|
|
85
|
+
suiUsdcPool("0x6b3791da0ae8b8d94d112c21b682e9f7d49a0b177cddd5b0dd61ca3ff27bc847", 500, 10),
|
|
86
|
+
suiUsdcPool("0xd477e8830f9aa070475149d75f285a4bd0a0386d8ce12f0e88e1c112cda21dfe", 1000, 20),
|
|
87
|
+
suiUsdcPool("0x1aed0146a85e0aa58639bfaca3ae55aa7db119eaeae35d3ec4a90742ebbb3933", 2000, 40),
|
|
88
|
+
suiUsdcPool("0x325239132e2b619147c00052986461cea02815172ea9d000c58e68484f514a90", 3000, 60),
|
|
89
|
+
suiUsdcPool("0x8903db2e9aea9e76d310c52a8745cff1f1d11fe38bc120828bd7280e7497ba8c", 10000, 200)
|
|
90
|
+
];
|
|
91
|
+
export function listFlowxPoolRegistry() {
|
|
92
|
+
return FLOWX_PINNED_POOLS;
|
|
93
|
+
}
|
|
94
|
+
export function getFlowxPoolById(poolId) {
|
|
95
|
+
return FLOWX_PINNED_POOLS.find((pool) => pool.poolId === poolId);
|
|
96
|
+
}
|
|
97
|
+
export function canonicalFlowxSymbol(symbol) {
|
|
98
|
+
const trimmed = symbol.trim();
|
|
99
|
+
if (!trimmed) {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
const matches = Object.values(FLOWX_PINNED_COINS).filter((coin) => coin.symbol.toLowerCase() === trimmed.toLowerCase());
|
|
103
|
+
return matches.length === 1 ? matches[0] : undefined;
|
|
104
|
+
}
|
|
105
|
+
export function resolveFlowxSwapPair(input) {
|
|
106
|
+
const source = canonicalFlowxSymbol(input.sourceSymbol);
|
|
107
|
+
const target = canonicalFlowxSymbol(input.targetSymbol);
|
|
108
|
+
if (!source || !target) {
|
|
109
|
+
throw new ReadServiceInputError("registry_miss", "FlowX symbol is not in the pinned registry", {
|
|
110
|
+
sourceSymbol: input.sourceSymbol,
|
|
111
|
+
targetSymbol: input.targetSymbol,
|
|
112
|
+
knownSymbols: Object.keys(FLOWX_PINNED_COINS)
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (source.symbol === target.symbol) {
|
|
116
|
+
throw new ReadServiceInputError("input_invalid", "FlowX swap pair uses the same symbol twice", {
|
|
117
|
+
sourceSymbol: input.sourceSymbol,
|
|
118
|
+
targetSymbol: input.targetSymbol
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const sourceType = normalizeCoinType(source.coinType);
|
|
122
|
+
const targetType = normalizeCoinType(target.coinType);
|
|
123
|
+
const xToY = FLOWX_PINNED_POOLS.filter((pool) => normalizeCoinType(pool.coinTypeX) === sourceType && normalizeCoinType(pool.coinTypeY) === targetType);
|
|
124
|
+
const yToX = FLOWX_PINNED_POOLS.filter((pool) => normalizeCoinType(pool.coinTypeX) === targetType && normalizeCoinType(pool.coinTypeY) === sourceType);
|
|
125
|
+
if (xToY.length > 0 && yToX.length > 0) {
|
|
126
|
+
throw new ReadServiceInputError("registry_miss", "FlowX pinned pools resolve the pair in both orientations", {
|
|
127
|
+
sourceSymbol: source.symbol,
|
|
128
|
+
targetSymbol: target.symbol
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
const pools = xToY.length > 0 ? xToY : yToX;
|
|
132
|
+
if (pools.length === 0) {
|
|
133
|
+
throw new ReadServiceInputError("registry_miss", "FlowX symbol pair has no pinned mainnet pools", {
|
|
134
|
+
sourceSymbol: source.symbol,
|
|
135
|
+
targetSymbol: target.symbol
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
source,
|
|
140
|
+
target,
|
|
141
|
+
swapXToY: xToY.length > 0,
|
|
142
|
+
pools
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
export function assertFlowxRegistryShape() {
|
|
146
|
+
const poolKeys = new Set();
|
|
147
|
+
const poolIds = new Set();
|
|
148
|
+
for (const pool of FLOWX_PINNED_POOLS) {
|
|
149
|
+
if (poolKeys.has(pool.poolKey)) {
|
|
150
|
+
throw new ReadServiceInputError("registry_miss", "FlowX pinned registry repeats a pool key", {
|
|
151
|
+
poolKey: pool.poolKey
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (poolIds.has(pool.poolId)) {
|
|
155
|
+
throw new ReadServiceInputError("registry_miss", "FlowX pinned registry repeats a pool id", {
|
|
156
|
+
poolId: pool.poolId
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
poolKeys.add(pool.poolKey);
|
|
160
|
+
poolIds.add(pool.poolId);
|
|
161
|
+
if (!Number.isInteger(pool.feeRate) || pool.feeRate < 0 || pool.feeRate >= FLOWX_CLMM_MAINNET.feeRateDenominator) {
|
|
162
|
+
throw new ReadServiceInputError("registry_miss", "FlowX pinned pool fee rate is outside the 1e6 denominator", {
|
|
163
|
+
poolKey: pool.poolKey,
|
|
164
|
+
feeRate: pool.feeRate
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (!Number.isInteger(pool.tickSpacing) || pool.tickSpacing <= 0) {
|
|
168
|
+
throw new ReadServiceInputError("registry_miss", "FlowX pinned pool tick spacing is not a positive integer", {
|
|
169
|
+
poolKey: pool.poolKey,
|
|
170
|
+
tickSpacing: pool.tickSpacing
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { INTENT_EVIDENCE_QUANTITY_KIND, INTENT_EVIDENCE_TARGET_ASSET_SELECTION_SOURCES } from "./readServiceTypes.js";
|
|
2
|
+
export function intentEvidenceQuantitySemantics() {
|
|
3
|
+
return {
|
|
4
|
+
kind: INTENT_EVIDENCE_QUANTITY_KIND,
|
|
5
|
+
allowedUse: "pre_transaction_evidence",
|
|
6
|
+
naturalLanguageIntentEvidence: true,
|
|
7
|
+
transactionBuildingAvailable: false,
|
|
8
|
+
signingReadinessAvailable: false,
|
|
9
|
+
routeRecommendationAvailable: false,
|
|
10
|
+
fiatUsdCashOutAvailable: false,
|
|
11
|
+
profitAndLossAvailable: false,
|
|
12
|
+
costBasisAvailable: false,
|
|
13
|
+
notFor: [
|
|
14
|
+
"transaction_building",
|
|
15
|
+
"signing_data",
|
|
16
|
+
"signing_readiness",
|
|
17
|
+
"payment_execution",
|
|
18
|
+
"best_route",
|
|
19
|
+
"route_recommendation",
|
|
20
|
+
"fiat_usd_cash_out",
|
|
21
|
+
"external_market_price_conversion",
|
|
22
|
+
"profit_or_pnl",
|
|
23
|
+
"cost_basis"
|
|
24
|
+
]
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function isSupportedIntentEvidenceKind(intentKind) {
|
|
28
|
+
return intentKind === "cover_payment_like_amount" || intentKind === "summarize_settlement_asset_group_balance";
|
|
29
|
+
}
|
|
30
|
+
export function isIntentEvidenceTargetAssetSelectionSource(source) {
|
|
31
|
+
return INTENT_EVIDENCE_TARGET_ASSET_SELECTION_SOURCES.includes(source);
|
|
32
|
+
}
|
|
33
|
+
export function intentEvidenceSettlementAssetCoverageBoundary() {
|
|
34
|
+
return [
|
|
35
|
+
"current_wallet_coin_balance_snapshot",
|
|
36
|
+
"settlement_asset_assets_only",
|
|
37
|
+
"not_settlement_token_selection",
|
|
38
|
+
"not_route_dependent_payment_support",
|
|
39
|
+
"not_payment_execution_readiness",
|
|
40
|
+
"not_gas_readiness"
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
export function intentEvidenceResponseEvidence(targetAsset, settlementAssetCoverage, candidateConversions) {
|
|
44
|
+
const settlementAssetClaims = intentEvidenceSettlementAssetResponseClaims(settlementAssetCoverage);
|
|
45
|
+
if (targetAsset === undefined || isIntentEvidenceSettlementAssetCoverageUnavailable(settlementAssetCoverage)) {
|
|
46
|
+
return {
|
|
47
|
+
mode: "settlement_asset_only",
|
|
48
|
+
primaryEvidenceFields: ["responseSummary"],
|
|
49
|
+
supportedResponseClaims: [...settlementAssetClaims, "required_user_choices", "unsupported_inferences"]
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
mode: "selected_target_context",
|
|
54
|
+
primaryEvidenceFields: [
|
|
55
|
+
"responseSummary",
|
|
56
|
+
"selectedTarget",
|
|
57
|
+
"candidateConversions",
|
|
58
|
+
"requiredUserChoices"
|
|
59
|
+
],
|
|
60
|
+
supportedResponseClaims: [
|
|
61
|
+
...settlementAssetClaims,
|
|
62
|
+
"selected_target_shortfall",
|
|
63
|
+
...(candidateConversions.some((candidate) => candidate.status === "quoted")
|
|
64
|
+
? ["direct_pool_quote_evidence"]
|
|
65
|
+
: []),
|
|
66
|
+
"required_user_choices",
|
|
67
|
+
"unsupported_inferences"
|
|
68
|
+
]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function intentEvidenceSettlementAssetResponseClaims(settlementAssetCoverage) {
|
|
72
|
+
if (settlementAssetCoverage.status === "balance_total_only") {
|
|
73
|
+
return ["current_settlement_asset_total"];
|
|
74
|
+
}
|
|
75
|
+
if (isIntentEvidenceSettlementAssetCoverageUnavailable(settlementAssetCoverage)) {
|
|
76
|
+
return ["settlement_asset_coverage_unavailable"];
|
|
77
|
+
}
|
|
78
|
+
return ["settlement_asset_coverage_status", "settlement_asset_shortfall"];
|
|
79
|
+
}
|
|
80
|
+
export function intentEvidenceSupportedClaims(settlementAssetCoverage, selectedTarget, candidateConversions) {
|
|
81
|
+
if (isIntentEvidenceSettlementAssetCoverageUnavailable(settlementAssetCoverage)) {
|
|
82
|
+
return ["settlement_asset_coverage_unavailable"];
|
|
83
|
+
}
|
|
84
|
+
const claims = [
|
|
85
|
+
"current_wallet_usd_settlement_coin_balance_snapshot",
|
|
86
|
+
"verified_display_amounts_from_pinned_or_onchain_decimals",
|
|
87
|
+
"settlement_asset_balance_total_when_common_decimals_are_available"
|
|
88
|
+
];
|
|
89
|
+
if (settlementAssetCoverage.status !== "balance_total_only") {
|
|
90
|
+
claims.push("settlement_asset_shortfall_when_common_decimals_are_available");
|
|
91
|
+
}
|
|
92
|
+
if (selectedTarget !== undefined && candidateConversions.some((candidate) => candidate.status === "quoted")) {
|
|
93
|
+
claims.push("direct_deepbook_pool_and_quote_evidence_when_target_asset_is_selected");
|
|
94
|
+
}
|
|
95
|
+
return claims;
|
|
96
|
+
}
|
|
97
|
+
function intentEvidenceAnswerCompleteness(input) {
|
|
98
|
+
if (isIntentEvidenceSettlementAssetCoverageUnavailable(input.settlementAssetCoverage)) {
|
|
99
|
+
return {
|
|
100
|
+
answerCompleteFor: "settlement_asset_coverage_unavailable_answer",
|
|
101
|
+
requiredAnswerFields: [
|
|
102
|
+
"responseSummary.unavailableReason",
|
|
103
|
+
"blockedReasons",
|
|
104
|
+
"responseSummary.requiredUserChoices"
|
|
105
|
+
],
|
|
106
|
+
notCompleteFor: [
|
|
107
|
+
"settlement_asset_balance_total",
|
|
108
|
+
"payment_coverage_status",
|
|
109
|
+
"payment_shortfall",
|
|
110
|
+
"selected_target_context",
|
|
111
|
+
"route_dependent_payment_support",
|
|
112
|
+
"payment_execution_readiness",
|
|
113
|
+
"transaction_building",
|
|
114
|
+
"signing_readiness"
|
|
115
|
+
]
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (input.responseEvidenceMode === "selected_target_context") {
|
|
119
|
+
return {
|
|
120
|
+
answerCompleteFor: "selected_target_context_answer",
|
|
121
|
+
requiredAnswerFields: ["responseSummary", "selectedTarget", "candidateConversions", "requiredUserChoices"],
|
|
122
|
+
notCompleteFor: [
|
|
123
|
+
"route_dependent_payment_support",
|
|
124
|
+
"settlement_token_selection",
|
|
125
|
+
"payment_execution_readiness",
|
|
126
|
+
"transaction_building",
|
|
127
|
+
"signing_readiness"
|
|
128
|
+
]
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
answerCompleteFor: "settlement_asset_group_answer",
|
|
133
|
+
requiredAnswerFields: ["responseSummary"],
|
|
134
|
+
notCompleteFor: [
|
|
135
|
+
"selected_target_context",
|
|
136
|
+
"route_dependent_payment_support",
|
|
137
|
+
"settlement_token_selection",
|
|
138
|
+
"payment_execution_readiness",
|
|
139
|
+
"transaction_building",
|
|
140
|
+
"signing_readiness"
|
|
141
|
+
]
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export function isIntentEvidenceSettlementAssetCoverageUnavailable(settlementAssetCoverage) {
|
|
145
|
+
return (settlementAssetCoverage.status === "unavailable_mixed_decimals" ||
|
|
146
|
+
settlementAssetCoverage.status === "unavailable_wallet_balance_scan_incomplete");
|
|
147
|
+
}
|
|
148
|
+
export function intentEvidenceResponseSummary(input) {
|
|
149
|
+
const questionKind = input.intentKind === "cover_payment_like_amount" ? "payment_coverage" : "settlement_asset_group_balance_total";
|
|
150
|
+
const answerCompleteness = intentEvidenceAnswerCompleteness({
|
|
151
|
+
settlementAssetCoverage: input.settlementAssetCoverage,
|
|
152
|
+
responseEvidenceMode: input.responseEvidenceMode
|
|
153
|
+
});
|
|
154
|
+
const base = {
|
|
155
|
+
questionKind,
|
|
156
|
+
answerCompleteness,
|
|
157
|
+
doNotCallQuoteToolsForThisQuestion: true,
|
|
158
|
+
coverageBasis: "settlement_asset_wallet_balance_only",
|
|
159
|
+
assetGroupId: input.assetGroupId,
|
|
160
|
+
requiredUserChoices: input.requiredUserChoices,
|
|
161
|
+
separateQuoteOutputs: {
|
|
162
|
+
usedForPaymentAnswer: false,
|
|
163
|
+
usedForShortfallAnswer: false,
|
|
164
|
+
reason: "separate_quote_tool_outputs_are_price_estimates_only",
|
|
165
|
+
paymentAnswerField: "responseSummary"
|
|
166
|
+
},
|
|
167
|
+
doNotUseForConclusion: [
|
|
168
|
+
"separate_quote_tool_results",
|
|
169
|
+
"assets_outside_settlement_group",
|
|
170
|
+
"route_dependent_payment_support"
|
|
171
|
+
],
|
|
172
|
+
excludedFromConclusion: [
|
|
173
|
+
"separate_quote_tool_results",
|
|
174
|
+
"candidate_conversion_quote_evidence",
|
|
175
|
+
"assets_outside_settlement_group",
|
|
176
|
+
"settlement_token_selection",
|
|
177
|
+
"route_dependent_payment_support",
|
|
178
|
+
"gas_reserve_or_fee_readiness",
|
|
179
|
+
"payment_execution_readiness",
|
|
180
|
+
"transaction_building",
|
|
181
|
+
"signing_readiness",
|
|
182
|
+
"fiat_usd_cash_out",
|
|
183
|
+
"profit_or_pnl",
|
|
184
|
+
"cost_basis"
|
|
185
|
+
]
|
|
186
|
+
};
|
|
187
|
+
if (input.settlementAssetCoverage.status === "balance_total_only") {
|
|
188
|
+
return {
|
|
189
|
+
...base,
|
|
190
|
+
conclusionKind: "current_settlement_asset_total",
|
|
191
|
+
currentDisplayAmount: input.settlementAssetCoverage.currentDisplayAmount,
|
|
192
|
+
requiredDisplayAmount: null,
|
|
193
|
+
shortfallDisplayAmount: null,
|
|
194
|
+
amountsUsedForAnswer: {
|
|
195
|
+
currentDisplayAmount: "current_wallet_balance_in_settlement_asset_group",
|
|
196
|
+
requiredDisplayAmount: null,
|
|
197
|
+
shortfallDisplayAmount: null
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (isIntentEvidenceSettlementAssetCoverageUnavailable(input.settlementAssetCoverage)) {
|
|
202
|
+
return {
|
|
203
|
+
...base,
|
|
204
|
+
conclusionKind: "settlement_asset_coverage_unavailable",
|
|
205
|
+
currentDisplayAmount: null,
|
|
206
|
+
requiredDisplayAmount: input.settlementAssetCoverage.requiredDisplayAmount ?? null,
|
|
207
|
+
shortfallDisplayAmount: null,
|
|
208
|
+
unavailableReason: input.settlementAssetCoverage.reason,
|
|
209
|
+
amountsUsedForAnswer: {
|
|
210
|
+
currentDisplayAmount: null,
|
|
211
|
+
requiredDisplayAmount: input.settlementAssetCoverage.requiredDisplayAmount === undefined ? null : "amount_requested_by_user",
|
|
212
|
+
shortfallDisplayAmount: null
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
...base,
|
|
218
|
+
conclusionKind: input.settlementAssetCoverage.status,
|
|
219
|
+
currentDisplayAmount: input.settlementAssetCoverage.currentDisplayAmount,
|
|
220
|
+
requiredDisplayAmount: input.settlementAssetCoverage.requiredDisplayAmount,
|
|
221
|
+
shortfallDisplayAmount: input.settlementAssetCoverage.shortfallDisplayAmount,
|
|
222
|
+
amountsUsedForAnswer: {
|
|
223
|
+
currentDisplayAmount: "current_wallet_balance_in_settlement_asset_group",
|
|
224
|
+
requiredDisplayAmount: "amount_requested_by_user",
|
|
225
|
+
shortfallDisplayAmount: "required_amount_minus_current_settlement_asset_balance"
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|