@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,229 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { MIST_PER_SUI, SUI_DECIMALS } from "@mysten/sui/utils";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { parseSuiAddress } from "../suiAddress.js";
|
|
5
|
+
import { classifySuiDeFiActivity, protocolActivityClassifierMatchSchema } from "./transactionActivityClassifier.js";
|
|
6
|
+
export const EXTERNAL_ACTIVITY_TRANSACTION_DETAIL_JSON_MAX_BYTES = 64 * 1024;
|
|
7
|
+
export const SUI_GAS_UNIT_SOURCE = "@mysten/sui MIST_PER_SUI";
|
|
8
|
+
export const externalActivityGasCostFactSchema = z.object({
|
|
9
|
+
netCostRaw: z.string().regex(/^-?\d+$/),
|
|
10
|
+
rawUnit: z.literal("MIST"),
|
|
11
|
+
display: z.string().regex(/^-?\d+(?:\.\d+)?$/),
|
|
12
|
+
displayUnit: z.literal("SUI"),
|
|
13
|
+
decimals: z.literal(SUI_DECIMALS),
|
|
14
|
+
unitSource: z.literal(SUI_GAS_UNIT_SOURCE)
|
|
15
|
+
}).strict();
|
|
16
|
+
export const externalActivityTransactionDetailSchema = z.object({
|
|
17
|
+
transactionKind: z.string().optional(),
|
|
18
|
+
moveCalls: z.array(z.object({
|
|
19
|
+
commandIndex: z.number().int().nonnegative(),
|
|
20
|
+
package: z.string(),
|
|
21
|
+
module: z.string(),
|
|
22
|
+
function: z.string(),
|
|
23
|
+
target: z.string()
|
|
24
|
+
}).strict()),
|
|
25
|
+
balanceChanges: z.array(z.object({
|
|
26
|
+
index: z.number().int().nonnegative(),
|
|
27
|
+
owner: z.string().optional(),
|
|
28
|
+
coinType: z.string(),
|
|
29
|
+
amountRaw: z.string().regex(/^-?\d+$/),
|
|
30
|
+
direction: z.enum(["increase", "decrease", "zero"])
|
|
31
|
+
}).strict()),
|
|
32
|
+
objectChanges: z.array(z.object({
|
|
33
|
+
index: z.number().int().nonnegative(),
|
|
34
|
+
objectId: z.string(),
|
|
35
|
+
changeKind: z.enum(["created", "mutated", "deleted"]),
|
|
36
|
+
inputType: z.string().optional(),
|
|
37
|
+
outputType: z.string().optional()
|
|
38
|
+
}).strict()),
|
|
39
|
+
events: z.array(z.object({
|
|
40
|
+
sequenceNumber: z.string().regex(/^\d+$/),
|
|
41
|
+
sender: z.string().optional(),
|
|
42
|
+
package: z.string().optional(),
|
|
43
|
+
module: z.string().optional(),
|
|
44
|
+
eventType: z.string().optional()
|
|
45
|
+
}).strict()),
|
|
46
|
+
gas: z.object({
|
|
47
|
+
gasObjectId: z.string().optional(),
|
|
48
|
+
computationCostRaw: z.string().regex(/^\d+$/).optional(),
|
|
49
|
+
storageCostRaw: z.string().regex(/^\d+$/).optional(),
|
|
50
|
+
storageRebateRaw: z.string().regex(/^\d+$/).optional(),
|
|
51
|
+
nonRefundableStorageFeeRaw: z.string().regex(/^\d+$/).optional(),
|
|
52
|
+
netGasCostRaw: z.string().regex(/^-?\d+$/).optional()
|
|
53
|
+
}).strict().optional(),
|
|
54
|
+
executionError: z.object({
|
|
55
|
+
message: z.string(),
|
|
56
|
+
abortCodeRaw: z.string().regex(/^\d+$/).optional(),
|
|
57
|
+
identifier: z.string().optional(),
|
|
58
|
+
instructionOffset: z.number().int().nonnegative().optional(),
|
|
59
|
+
sourceLineNumber: z.number().int().nonnegative().optional(),
|
|
60
|
+
package: z.string().optional(),
|
|
61
|
+
module: z.string().optional(),
|
|
62
|
+
function: z.string().optional()
|
|
63
|
+
}).strict().optional(),
|
|
64
|
+
truncation: z.object({
|
|
65
|
+
moveCalls: z.boolean(),
|
|
66
|
+
balanceChanges: z.boolean(),
|
|
67
|
+
objectChanges: z.boolean(),
|
|
68
|
+
events: z.boolean()
|
|
69
|
+
}).strict()
|
|
70
|
+
}).strict();
|
|
71
|
+
export const externalActivityTransactionCompactFactsSchema = z.object({
|
|
72
|
+
factScope: z.literal("transaction"),
|
|
73
|
+
requestedAccountScoped: z.literal(false),
|
|
74
|
+
moveCallTargets: z.array(z.string()),
|
|
75
|
+
balanceChanges: z.array(z.object({
|
|
76
|
+
coinType: z.string(),
|
|
77
|
+
amountRaw: z.string().regex(/^-?\d+$/),
|
|
78
|
+
direction: z.enum(["increase", "decrease", "zero"]),
|
|
79
|
+
count: z.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional()
|
|
80
|
+
}).strict()),
|
|
81
|
+
objectChangeCounts: z.object({
|
|
82
|
+
created: z.number().int().nonnegative(),
|
|
83
|
+
mutated: z.number().int().nonnegative(),
|
|
84
|
+
deleted: z.number().int().nonnegative()
|
|
85
|
+
}).strict(),
|
|
86
|
+
eventTypes: z.array(z.string()),
|
|
87
|
+
gasCost: externalActivityGasCostFactSchema.optional(),
|
|
88
|
+
gasNetCostRaw: z.string().regex(/^-?\d+$/).optional(),
|
|
89
|
+
executionError: z.object({
|
|
90
|
+
message: z.string(),
|
|
91
|
+
abortCodeRaw: z.string().regex(/^\d+$/).optional(),
|
|
92
|
+
package: z.string().optional(),
|
|
93
|
+
module: z.string().optional(),
|
|
94
|
+
function: z.string().optional()
|
|
95
|
+
}).strict().optional(),
|
|
96
|
+
detailTruncated: z.boolean(),
|
|
97
|
+
protocolMatches: z.array(protocolActivityClassifierMatchSchema).optional()
|
|
98
|
+
}).strict();
|
|
99
|
+
export function externalActivityTransactionDetailJsonByteLength(value) {
|
|
100
|
+
return Buffer.byteLength(value, "utf8");
|
|
101
|
+
}
|
|
102
|
+
export function sanitizeExternalActivityTransactionDetailsForKnownAccount(details, storageAccount) {
|
|
103
|
+
return {
|
|
104
|
+
...details,
|
|
105
|
+
balanceChanges: details.balanceChanges.map((change) => {
|
|
106
|
+
if (addressMatches(change.owner, storageAccount)) {
|
|
107
|
+
return { ...change, owner: storageAccount };
|
|
108
|
+
}
|
|
109
|
+
const { owner: _owner, ...withoutOwner } = change;
|
|
110
|
+
return withoutOwner;
|
|
111
|
+
}),
|
|
112
|
+
events: details.events.map((event) => {
|
|
113
|
+
if (addressMatches(event.sender, storageAccount)) {
|
|
114
|
+
return { ...event, sender: storageAccount };
|
|
115
|
+
}
|
|
116
|
+
const { sender: _sender, ...withoutSender } = event;
|
|
117
|
+
return withoutSender;
|
|
118
|
+
})
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
export function externalActivityTransactionTouchesAccount(transaction, account) {
|
|
122
|
+
return externalActivityTransactionBalanceOwners(transaction).includes(account);
|
|
123
|
+
}
|
|
124
|
+
export function externalActivityTransactionBalanceOwners(transaction) {
|
|
125
|
+
const owners = transaction.details?.balanceChanges.flatMap((change) => {
|
|
126
|
+
const owner = change.owner === undefined ? undefined : parseSuiAddress(change.owner);
|
|
127
|
+
return owner === undefined ? [] : [owner];
|
|
128
|
+
}) ?? [];
|
|
129
|
+
return [...new Set(owners)];
|
|
130
|
+
}
|
|
131
|
+
export function externalActivityTransactionDetailsReferenceOnlyAccount(details, account) {
|
|
132
|
+
return details.balanceChanges.every((change) => change.owner === undefined || addressMatches(change.owner, account))
|
|
133
|
+
&& details.events.every((event) => event.sender === undefined || addressMatches(event.sender, account));
|
|
134
|
+
}
|
|
135
|
+
export function compactExternalActivityTransactionDetails(details) {
|
|
136
|
+
const objectChangeCounts = {
|
|
137
|
+
created: 0,
|
|
138
|
+
mutated: 0,
|
|
139
|
+
deleted: 0
|
|
140
|
+
};
|
|
141
|
+
for (const change of details.objectChanges) {
|
|
142
|
+
objectChangeCounts[change.changeKind] += 1;
|
|
143
|
+
}
|
|
144
|
+
const executionError = details.executionError === undefined
|
|
145
|
+
? undefined
|
|
146
|
+
: {
|
|
147
|
+
message: details.executionError.message,
|
|
148
|
+
...(details.executionError.abortCodeRaw === undefined ? {} : { abortCodeRaw: details.executionError.abortCodeRaw }),
|
|
149
|
+
...(details.executionError.package === undefined ? {} : { package: details.executionError.package }),
|
|
150
|
+
...(details.executionError.module === undefined ? {} : { module: details.executionError.module }),
|
|
151
|
+
...(details.executionError.function === undefined ? {} : { function: details.executionError.function })
|
|
152
|
+
};
|
|
153
|
+
const protocolMatches = classifySuiDeFiActivity(details);
|
|
154
|
+
return {
|
|
155
|
+
factScope: "transaction",
|
|
156
|
+
requestedAccountScoped: false,
|
|
157
|
+
moveCallTargets: uniqueStrings(details.moveCalls.map((call) => call.target)),
|
|
158
|
+
balanceChanges: compactBalanceChanges(details.balanceChanges),
|
|
159
|
+
objectChangeCounts,
|
|
160
|
+
eventTypes: uniqueStrings(details.events.flatMap((event) => event.eventType === undefined ? [] : [event.eventType])),
|
|
161
|
+
...(details.gas?.netGasCostRaw === undefined ? {} : { gasCost: suiGasCostFact(details.gas.netGasCostRaw) }),
|
|
162
|
+
...(details.gas?.netGasCostRaw === undefined ? {} : { gasNetCostRaw: details.gas.netGasCostRaw }),
|
|
163
|
+
...(executionError === undefined ? {} : { executionError }),
|
|
164
|
+
detailTruncated: details.truncation.moveCalls
|
|
165
|
+
|| details.truncation.balanceChanges
|
|
166
|
+
|| details.truncation.objectChanges
|
|
167
|
+
|| details.truncation.events,
|
|
168
|
+
...(protocolMatches.length === 0 ? {} : { protocolMatches })
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
export function suiGasCostFact(netCostRaw) {
|
|
172
|
+
return {
|
|
173
|
+
netCostRaw,
|
|
174
|
+
rawUnit: "MIST",
|
|
175
|
+
display: formatSignedMistAsSui(netCostRaw),
|
|
176
|
+
displayUnit: "SUI",
|
|
177
|
+
decimals: SUI_DECIMALS,
|
|
178
|
+
unitSource: SUI_GAS_UNIT_SOURCE
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function formatSignedMistAsSui(raw) {
|
|
182
|
+
if (!/^-?\d+$/.test(raw)) {
|
|
183
|
+
throw new Error("gas raw amount must be a signed integer string");
|
|
184
|
+
}
|
|
185
|
+
const negative = raw.startsWith("-");
|
|
186
|
+
const unsignedRaw = negative ? raw.slice(1) : raw;
|
|
187
|
+
const amount = BigInt(unsignedRaw);
|
|
188
|
+
const whole = amount / MIST_PER_SUI;
|
|
189
|
+
const fractional = amount % MIST_PER_SUI;
|
|
190
|
+
const sign = negative && amount !== 0n ? "-" : "";
|
|
191
|
+
if (fractional === 0n) {
|
|
192
|
+
return `${sign}${whole.toString()}`;
|
|
193
|
+
}
|
|
194
|
+
const fractionalText = fractional
|
|
195
|
+
.toString()
|
|
196
|
+
.padStart(SUI_DECIMALS, "0")
|
|
197
|
+
.replace(/0+$/, "");
|
|
198
|
+
return `${sign}${whole.toString()}.${fractionalText}`;
|
|
199
|
+
}
|
|
200
|
+
function compactBalanceChanges(balanceChanges) {
|
|
201
|
+
const compacted = new Map();
|
|
202
|
+
for (const change of balanceChanges) {
|
|
203
|
+
const key = `${change.coinType}\n${change.amountRaw}\n${change.direction}`;
|
|
204
|
+
const existing = compacted.get(key);
|
|
205
|
+
if (existing === undefined) {
|
|
206
|
+
compacted.set(key, {
|
|
207
|
+
coinType: change.coinType,
|
|
208
|
+
amountRaw: change.amountRaw,
|
|
209
|
+
direction: change.direction,
|
|
210
|
+
count: 1
|
|
211
|
+
});
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
existing.count += 1;
|
|
215
|
+
}
|
|
216
|
+
return [...compacted.values()].map((change) => ({
|
|
217
|
+
coinType: change.coinType,
|
|
218
|
+
amountRaw: change.amountRaw,
|
|
219
|
+
direction: change.direction,
|
|
220
|
+
...(change.count === 1 ? {} : { count: change.count })
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
function uniqueStrings(values) {
|
|
224
|
+
return [...new Set(values)];
|
|
225
|
+
}
|
|
226
|
+
function addressMatches(candidate, account) {
|
|
227
|
+
const normalized = candidate === undefined ? undefined : parseSuiAddress(candidate);
|
|
228
|
+
return normalized !== undefined && normalized === account;
|
|
229
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { parseSuiAddress } from "../suiAddress.js";
|
|
2
|
+
export const protocolActivityPrimaryActions = [
|
|
3
|
+
"order",
|
|
4
|
+
"swap",
|
|
5
|
+
"liquidity",
|
|
6
|
+
"lending",
|
|
7
|
+
"fee_or_reward",
|
|
8
|
+
"admin_or_versioning",
|
|
9
|
+
"unknown"
|
|
10
|
+
];
|
|
11
|
+
const DEEPBOOK_PINNED_SDK_PACKAGE = "0xf48222c4e057fa468baf136bff8e12504209d43850c5778f76159292a96f621e";
|
|
12
|
+
const DEEPBOOK_DOCS_SNAPSHOT_PACKAGE = "0x337f4f4f6567fcd778d5454f27c16c70e2f274cc6377ea6249ddf491482ef497";
|
|
13
|
+
const DEEPTRADE_CORE_PACKAGE = "0xc10d536b6580d809711b9bb8eee3945d5e96f92a346c84d74ff7a0697e664695";
|
|
14
|
+
const CETUS_CLMM_PACKAGE = "0x25ebb9a7c50eb17b3fa9c5a30fb8b5ad8f97caaf4928943acbcff7153dfee5e3";
|
|
15
|
+
const SUILEND_MVR_CORE_PACKAGE = "0xe53906c2c058d1e369763114418f3c144d1b74960d29b2785718a782fec09b61";
|
|
16
|
+
const SUILEND_MAIN_MARKET_TYPE_PACKAGE = "0xf95b06141ed4a174f239417323bde3f209b972f5930d8521ea38a52aff3a6ddf";
|
|
17
|
+
const AFTERMATH_AFSUI_EVENTS_PACKAGE = "0x7f6ce7ade63857c4fd16ef7783fed2dfc4d7fb7e40615abdb653030b76aef0c6";
|
|
18
|
+
const AFTERMATH_AFSUI_PACKAGE = "0x1575034d2729907aefca1ac757d6ccfcd3fc7e9e77927523c06007d8353ad836";
|
|
19
|
+
export const SUI_DEFI_ACTIVITY_PROTOCOL_RULES = [
|
|
20
|
+
{
|
|
21
|
+
protocolId: "deepbook-v3",
|
|
22
|
+
displayName: "DeepBook V3",
|
|
23
|
+
activityCategory: "CLOB / order book",
|
|
24
|
+
packages: normalizePackageMap({
|
|
25
|
+
[DEEPBOOK_PINNED_SDK_PACKAGE]: {
|
|
26
|
+
source: "mvr_current_mainnet_resolution_and_pinned_sdk_local_registry",
|
|
27
|
+
mvrName: "@deepbook/core"
|
|
28
|
+
},
|
|
29
|
+
[DEEPBOOK_DOCS_SNAPSHOT_PACKAGE]: {
|
|
30
|
+
source: "sui_docs_research_snapshot",
|
|
31
|
+
limitation: "deepbook_package_conflict_open"
|
|
32
|
+
}
|
|
33
|
+
}),
|
|
34
|
+
sharedObjects: normalizeObjectMap({
|
|
35
|
+
"0xaf16199a2dff736e9f07a845f23c5da6df6f756eddb631aed9d24a93efc4549d": "deepbook_registry"
|
|
36
|
+
}),
|
|
37
|
+
actionForMoveCall: deepbookActionForMoveCall
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
protocolId: "deeptrade-core",
|
|
41
|
+
displayName: "DeepTrade Core",
|
|
42
|
+
activityCategory: "DeepBook wrapper and fee system",
|
|
43
|
+
packages: normalizePackageMap({
|
|
44
|
+
[DEEPTRADE_CORE_PACKAGE]: {
|
|
45
|
+
source: "mvr_current_mainnet_resolution_and_deeptrade_research_snapshot",
|
|
46
|
+
mvrName: "@deeptrade/deeptrade-core"
|
|
47
|
+
}
|
|
48
|
+
}),
|
|
49
|
+
sharedObjects: normalizeObjectMap({
|
|
50
|
+
"0xb90e2d3de41817016b7d39f49c724c5b0616bd30f1d5e6383048efafabe6232b": "deeptrade_treasury",
|
|
51
|
+
"0xe6a7158cbbee252f2ef9488663d91b42d84b3933609c3f891937240f4be65086": "deeptrade_pool_creation_config",
|
|
52
|
+
"0xcb757e55db3a502dc826c40b8ced507d017b41d926c5bf554e69855510bb855e": "deeptrade_trading_fee_config",
|
|
53
|
+
"0x6a06100001533356fb2e9f68ee299c15565777dfb28c741ec440cb08b168cbff": "deeptrade_loyalty_program"
|
|
54
|
+
}),
|
|
55
|
+
actionForMoveCall: deeptradeActionForMoveCall
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
protocolId: "cetus-clmm",
|
|
59
|
+
displayName: "Cetus CLMM",
|
|
60
|
+
activityCategory: "CLMM / AMM",
|
|
61
|
+
packages: normalizePackageMap({
|
|
62
|
+
[CETUS_CLMM_PACKAGE]: {
|
|
63
|
+
source: "mvr_current_mainnet_resolution_and_cetus_research_snapshot",
|
|
64
|
+
mvrName: "@cetuspackages/clmm"
|
|
65
|
+
}
|
|
66
|
+
}),
|
|
67
|
+
sharedObjects: normalizeObjectMap({
|
|
68
|
+
"0xdaa46292632c3c4d8f31f23ea0f9b36a28ff3677e9684980e4438403a67a3d8f": "cetus_global_config",
|
|
69
|
+
"0xf699e7f2276f5c9a75944b37a0c5b5d9ddfd2471bf6242483b03ab2887d198d0": "cetus_pools_table"
|
|
70
|
+
}),
|
|
71
|
+
actionForMoveCall: clmmActionForMoveCall
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
protocolId: "suilend-lending",
|
|
75
|
+
displayName: "Suilend Lending",
|
|
76
|
+
activityCategory: "Lending market",
|
|
77
|
+
packages: normalizePackageMap({
|
|
78
|
+
[SUILEND_MVR_CORE_PACKAGE]: {
|
|
79
|
+
source: "mvr_current_mainnet_resolution",
|
|
80
|
+
mvrName: "@suilend/core"
|
|
81
|
+
},
|
|
82
|
+
[SUILEND_MAIN_MARKET_TYPE_PACKAGE]: {
|
|
83
|
+
source: "suilend_research_snapshot_market_type",
|
|
84
|
+
matchKinds: ["eventType", "objectType"]
|
|
85
|
+
}
|
|
86
|
+
}),
|
|
87
|
+
sharedObjects: normalizeObjectMap({
|
|
88
|
+
"0x84030d26d85eaa7035084a057f2f11f701b7e2e4eda87551becbc7c97505ece1": "suilend_main_market",
|
|
89
|
+
"0xf7a4defe0b6566b6a2674a02a0c61c9f99bd012eed21bc741a069eaa82d35927": "suilend_main_market_owner_cap"
|
|
90
|
+
}),
|
|
91
|
+
actionForMoveCall: lendingActionForMoveCall
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
protocolId: "aftermath-afsui",
|
|
95
|
+
displayName: "Aftermath afSUI",
|
|
96
|
+
activityCategory: "Liquid staking",
|
|
97
|
+
packages: normalizePackageMap({
|
|
98
|
+
[AFTERMATH_AFSUI_EVENTS_PACKAGE]: {
|
|
99
|
+
source: "aftermath_research_snapshot",
|
|
100
|
+
matchKinds: ["eventType", "objectType"]
|
|
101
|
+
},
|
|
102
|
+
[AFTERMATH_AFSUI_PACKAGE]: {
|
|
103
|
+
source: "aftermath_research_snapshot",
|
|
104
|
+
matchKinds: ["eventType", "objectType"]
|
|
105
|
+
}
|
|
106
|
+
}),
|
|
107
|
+
sharedObjects: normalizeObjectMap({
|
|
108
|
+
"0x2f8f6d5da7f13ea37daa397724280483ed062769813b6f31e9788e59cc88994d": "aftermath_staked_sui_vault",
|
|
109
|
+
"0x55486449e41d89cfbdb20e005c1c5c1007858ad5b4d5d7c047d2b3b592fe8791": "aftermath_staked_sui_vault_state",
|
|
110
|
+
"0xd2b95022244757b0ab9f74e2ee2fb2c3bf29dce5590fa6993a85d64bd219d7e8": "aftermath_afsui_treasury"
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
];
|
|
114
|
+
function deepbookActionForMoveCall(call) {
|
|
115
|
+
if (call.module === "balance_manager") {
|
|
116
|
+
if (/^(deposit|withdraw|withdraw_all|mint_trade_cap|mint_deposit_cap|mint_withdraw_cap)/.test(call.function)) {
|
|
117
|
+
return "liquidity";
|
|
118
|
+
}
|
|
119
|
+
return "unknown";
|
|
120
|
+
}
|
|
121
|
+
if (call.module !== "pool") {
|
|
122
|
+
return "unknown";
|
|
123
|
+
}
|
|
124
|
+
if (/^(place_|modify_order|cancel_|withdraw_settled)/.test(call.function)) {
|
|
125
|
+
return "order";
|
|
126
|
+
}
|
|
127
|
+
if (/^swap_/.test(call.function)) {
|
|
128
|
+
return "swap";
|
|
129
|
+
}
|
|
130
|
+
if (/^(claim_|mint_referral|update_.*referral|burn_deep)/.test(call.function)) {
|
|
131
|
+
return "fee_or_reward";
|
|
132
|
+
}
|
|
133
|
+
if (/^(stake|unstake|submit_proposal|vote|create_|update_|adjust_|enable_|set_)/.test(call.function)) {
|
|
134
|
+
return "admin_or_versioning";
|
|
135
|
+
}
|
|
136
|
+
if (/^borrow_flashloan|^return_flashloan/.test(call.function)) {
|
|
137
|
+
return "liquidity";
|
|
138
|
+
}
|
|
139
|
+
return "unknown";
|
|
140
|
+
}
|
|
141
|
+
function deeptradeActionForMoveCall(call) {
|
|
142
|
+
if (call.module === "dt_order") {
|
|
143
|
+
return "order";
|
|
144
|
+
}
|
|
145
|
+
const combined = `${call.module}_${call.function}`;
|
|
146
|
+
if (isAdminOrVersioningCall(combined) || /multisig|dt_pool/.test(call.module) || /create_permissionless_pool/.test(call.function)) {
|
|
147
|
+
return "admin_or_versioning";
|
|
148
|
+
}
|
|
149
|
+
if (call.module === "swap") {
|
|
150
|
+
return "swap";
|
|
151
|
+
}
|
|
152
|
+
if (/fee|treasury|loyalty/.test(call.module) || /fee|loyalty|reserve/.test(call.function)) {
|
|
153
|
+
return "fee_or_reward";
|
|
154
|
+
}
|
|
155
|
+
return "unknown";
|
|
156
|
+
}
|
|
157
|
+
function clmmActionForMoveCall(call) {
|
|
158
|
+
const combined = `${call.module}_${call.function}`;
|
|
159
|
+
if (isAdminOrVersioningCall(combined)) {
|
|
160
|
+
return "admin_or_versioning";
|
|
161
|
+
}
|
|
162
|
+
if (/swap|exchange/.test(combined)) {
|
|
163
|
+
return "swap";
|
|
164
|
+
}
|
|
165
|
+
if (/fee|reward|collect|claim/.test(combined)) {
|
|
166
|
+
return "fee_or_reward";
|
|
167
|
+
}
|
|
168
|
+
if (/liquidity|position|mint|burn|open|close|increase|decrease/.test(combined)) {
|
|
169
|
+
return "liquidity";
|
|
170
|
+
}
|
|
171
|
+
return "unknown";
|
|
172
|
+
}
|
|
173
|
+
function lendingActionForMoveCall(call) {
|
|
174
|
+
const combined = `${call.module}_${call.function}`;
|
|
175
|
+
if (isAdminOrVersioningCall(combined) || /config|owner|risk|isolated|oracle/.test(combined)) {
|
|
176
|
+
return "admin_or_versioning";
|
|
177
|
+
}
|
|
178
|
+
if (/deposit|withdraw|borrow|repay|liquidat|redeem|mint|supply/.test(combined)) {
|
|
179
|
+
return "lending";
|
|
180
|
+
}
|
|
181
|
+
if (/reward|fee|claim/.test(combined)) {
|
|
182
|
+
return "fee_or_reward";
|
|
183
|
+
}
|
|
184
|
+
return "unknown";
|
|
185
|
+
}
|
|
186
|
+
export function protocolPackageRuleAllows(rule, kind) {
|
|
187
|
+
return rule.matchKinds === undefined || rule.matchKinds.includes(kind);
|
|
188
|
+
}
|
|
189
|
+
function isAdminOrVersioningCall(value) {
|
|
190
|
+
const tokens = value.split("_").filter((token) => token.length > 0);
|
|
191
|
+
return tokens.some((token) => [
|
|
192
|
+
"admin",
|
|
193
|
+
"config",
|
|
194
|
+
"owner",
|
|
195
|
+
"risk",
|
|
196
|
+
"oracle",
|
|
197
|
+
"version",
|
|
198
|
+
"registry",
|
|
199
|
+
"govern",
|
|
200
|
+
"pause",
|
|
201
|
+
"upgrade",
|
|
202
|
+
"set",
|
|
203
|
+
"update",
|
|
204
|
+
"allowed"
|
|
205
|
+
].includes(token));
|
|
206
|
+
}
|
|
207
|
+
function normalizePackageMap(packages) {
|
|
208
|
+
return Object.fromEntries(Object.entries(packages).flatMap(([address, value]) => {
|
|
209
|
+
const normalized = parseSuiAddress(address);
|
|
210
|
+
return normalized === undefined ? [] : [[normalized, value]];
|
|
211
|
+
}));
|
|
212
|
+
}
|
|
213
|
+
function normalizeObjectMap(objects) {
|
|
214
|
+
return Object.fromEntries(Object.entries(objects).flatMap(([address, label]) => {
|
|
215
|
+
const normalized = parseSuiAddress(address);
|
|
216
|
+
return normalized === undefined ? [] : [[normalized, label]];
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { EXTERNAL_ACTIVITY_SCAN_DEFAULT_LIMIT, EXTERNAL_ACTIVITY_SCAN_MAX_LIMIT } from "./activityStore.js";
|
|
2
|
+
import { externalActivityTransactionTouchesAccount } from "./transactionActivityDetails.js";
|
|
3
|
+
import { TransactionActivityError } from "./transactionActivityTypes.js";
|
|
4
|
+
export function normalizeActivityLimit(limit) {
|
|
5
|
+
if (limit === undefined) {
|
|
6
|
+
return EXTERNAL_ACTIVITY_SCAN_DEFAULT_LIMIT;
|
|
7
|
+
}
|
|
8
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > EXTERNAL_ACTIVITY_SCAN_MAX_LIMIT) {
|
|
9
|
+
throw new TransactionActivityError("input_invalid", "limit must be an integer from 1 to 100", {
|
|
10
|
+
limit,
|
|
11
|
+
min: 1,
|
|
12
|
+
max: EXTERNAL_ACTIVITY_SCAN_MAX_LIMIT
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return limit;
|
|
16
|
+
}
|
|
17
|
+
export function normalizeCheckpointBound(value, field) {
|
|
18
|
+
if (value === undefined) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
if (!/^\d+$/.test(value)) {
|
|
22
|
+
throw new TransactionActivityError("input_invalid", "checkpoint bounds must be unsigned integer strings", { field });
|
|
23
|
+
}
|
|
24
|
+
if (BigInt(value) > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
25
|
+
throw new TransactionActivityError("input_invalid", "checkpoint bounds exceed the current GraphQL numeric filter range", {
|
|
26
|
+
field,
|
|
27
|
+
max: String(Number.MAX_SAFE_INTEGER)
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
export function assertCheckpointRange(fromCheckpoint, toCheckpoint) {
|
|
33
|
+
if (fromCheckpoint !== undefined && toCheckpoint !== undefined && BigInt(fromCheckpoint) > BigInt(toCheckpoint)) {
|
|
34
|
+
throw new TransactionActivityError("input_invalid", "fromCheckpoint must be less than or equal to toCheckpoint", {
|
|
35
|
+
fromCheckpoint,
|
|
36
|
+
toCheckpoint
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function normalizeTimestampBound(value, field) {
|
|
41
|
+
if (value === undefined) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
const parsed = new Date(value);
|
|
45
|
+
if (Number.isNaN(parsed.getTime()) || parsed.toISOString() !== value) {
|
|
46
|
+
throw new TransactionActivityError("input_invalid", "timestamp bounds must be ISO 8601 UTC timestamps", { field });
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
export function assertTimestampRange(fromTimestamp, toTimestamp) {
|
|
51
|
+
if (fromTimestamp !== undefined && toTimestamp !== undefined && fromTimestamp > toTimestamp) {
|
|
52
|
+
throw new TransactionActivityError("input_invalid", "fromTimestamp must be less than or equal to toTimestamp", {
|
|
53
|
+
fromTimestamp,
|
|
54
|
+
toTimestamp
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function isMonotonicActivityOrder(transactions) {
|
|
59
|
+
let direction;
|
|
60
|
+
for (let index = 1; index < transactions.length; index += 1) {
|
|
61
|
+
const previous = transactions[index - 1];
|
|
62
|
+
const current = transactions[index];
|
|
63
|
+
const comparison = compareActivityFactTimeAscending(previous, current);
|
|
64
|
+
if (comparison === 0) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const pairDirection = comparison < 0 ? "ascending" : "descending";
|
|
68
|
+
if (direction === undefined) {
|
|
69
|
+
direction = pairDirection;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (direction !== pairDirection) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
export function compareActivityFactsDescending(a, b) {
|
|
79
|
+
return -compareActivityFactsAscending(a, b);
|
|
80
|
+
}
|
|
81
|
+
export function windowCompletion(input, page, orderingVerified) {
|
|
82
|
+
const hasLowerBound = input.fromCheckpoint !== undefined || input.fromTimestamp !== undefined;
|
|
83
|
+
const hasAnyWindowBound = hasLowerBound || input.toCheckpoint !== undefined || input.toTimestamp !== undefined;
|
|
84
|
+
if (!hasAnyWindowBound) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
if (!page.hasMore) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
if (!orderingVerified) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const reachedCheckpoint = input.fromCheckpoint === undefined
|
|
94
|
+
? false
|
|
95
|
+
: page.transactions.some((transaction) => transaction.checkpoint !== undefined && BigInt(transaction.checkpoint) <= BigInt(input.fromCheckpoint));
|
|
96
|
+
const reachedTimestamp = input.fromTimestamp === undefined
|
|
97
|
+
? false
|
|
98
|
+
: page.transactions.some((transaction) => transaction.timestamp !== undefined && transaction.timestamp <= input.fromTimestamp);
|
|
99
|
+
return reachedCheckpoint || reachedTimestamp;
|
|
100
|
+
}
|
|
101
|
+
export function incompleteReasonForScan(input) {
|
|
102
|
+
if (!input.orderingVerified) {
|
|
103
|
+
return "ordering_unverified";
|
|
104
|
+
}
|
|
105
|
+
return input.windowComplete === false ? "limit_reached" : undefined;
|
|
106
|
+
}
|
|
107
|
+
export function filterTransactionsForRequestedWindow(transactions, input) {
|
|
108
|
+
return transactions.filter((transaction) => {
|
|
109
|
+
if (input.relationship === "sent" && transaction.sender !== input.account) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (input.fromCheckpoint !== undefined && (transaction.checkpoint === undefined || BigInt(transaction.checkpoint) < BigInt(input.fromCheckpoint))) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (input.toCheckpoint !== undefined && (transaction.checkpoint === undefined || BigInt(transaction.checkpoint) > BigInt(input.toCheckpoint))) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (input.fromTimestamp !== undefined && (transaction.timestamp === undefined || transaction.timestamp < input.fromTimestamp)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
if (input.toTimestamp !== undefined && (transaction.timestamp === undefined || transaction.timestamp > input.toTimestamp)) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
export function transactionMatchesKnownStorageAccount(transaction, account, relationship) {
|
|
128
|
+
if (relationship === "sent") {
|
|
129
|
+
return transaction.sender === account;
|
|
130
|
+
}
|
|
131
|
+
return transaction.sender === account || externalActivityTransactionTouchesAccount(transaction, account);
|
|
132
|
+
}
|
|
133
|
+
function compareActivityFactsAscending(a, b) {
|
|
134
|
+
const timeComparison = compareActivityFactTimeAscending(a, b);
|
|
135
|
+
return timeComparison === 0 ? compareStringsAscending(a.digest, b.digest) : timeComparison;
|
|
136
|
+
}
|
|
137
|
+
function compareActivityFactTimeAscending(a, b) {
|
|
138
|
+
if (a.checkpoint !== undefined && b.checkpoint !== undefined) {
|
|
139
|
+
const checkpointDelta = BigInt(a.checkpoint) - BigInt(b.checkpoint);
|
|
140
|
+
if (checkpointDelta < 0n)
|
|
141
|
+
return -1;
|
|
142
|
+
if (checkpointDelta > 0n)
|
|
143
|
+
return 1;
|
|
144
|
+
}
|
|
145
|
+
else if (a.checkpoint !== undefined) {
|
|
146
|
+
return 1;
|
|
147
|
+
}
|
|
148
|
+
else if (b.checkpoint !== undefined) {
|
|
149
|
+
return -1;
|
|
150
|
+
}
|
|
151
|
+
if (a.timestamp !== undefined && b.timestamp !== undefined) {
|
|
152
|
+
const timestampDelta = compareStringsAscending(a.timestamp, b.timestamp);
|
|
153
|
+
if (timestampDelta !== 0)
|
|
154
|
+
return timestampDelta;
|
|
155
|
+
}
|
|
156
|
+
else if (a.timestamp !== undefined) {
|
|
157
|
+
return 1;
|
|
158
|
+
}
|
|
159
|
+
else if (b.timestamp !== undefined) {
|
|
160
|
+
return -1;
|
|
161
|
+
}
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
function compareStringsAscending(a, b) {
|
|
165
|
+
if (a < b)
|
|
166
|
+
return -1;
|
|
167
|
+
if (a > b)
|
|
168
|
+
return 1;
|
|
169
|
+
return 0;
|
|
170
|
+
}
|