{"version":3,"file":"core.mjs","names":["bytes","transactionResponse"],"sources":["../../../src/transaction-analyzer/rules/core.ts"],"sourcesContent":["// Copyright (c) Mysten Labs, Inc.\n// SPDX-License-Identifier: Apache-2.0\n\nimport type { Transaction } from '@mysten/sui/transactions';\nimport { TransactionDataBuilder } from '@mysten/sui/transactions';\nimport type { ClientWithCoreApi, SuiClientTypes } from '@mysten/sui/client';\nimport type { Analyzer, AnalyzerOutput } from '../analyzer.js';\nimport { createAnalyzer } from '../analyzer.js';\n\nexport const bytes = createAnalyzer({\n\tcacheKey: 'bytes@1.0.0',\n\tanalyze:\n\t\t(options: { client: ClientWithCoreApi }, transaction: Transaction) =>\n\t\tasync (): Promise<AnalyzerOutput<Uint8Array>> => {\n\t\t\ttry {\n\t\t\t\treturn {\n\t\t\t\t\tresult: await transaction.build({ client: options.client }),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\t// Building can throw for many reasons (object resolution, a missing client,\n\t\t\t\t// a malformed transaction) — keep the underlying detail instead of a generic\n\t\t\t\t// message, and attach the error for programmatic inspection.\n\t\t\t\treturn {\n\t\t\t\t\tissues: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmessage: `Failed to build transaction: ${(error as Error).message}`,\n\t\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t},\n});\n\nexport const data = createAnalyzer({\n\tdependencies: { bytes },\n\tanalyze: (_, tx) => () => {\n\t\treturn { result: tx.getData() };\n\t},\n});\n\nexport const digest = createAnalyzer({\n\tdependencies: { bytes },\n\tanalyze:\n\t\t() =>\n\t\t({ bytes }) => {\n\t\t\treturn { result: TransactionDataBuilder.getDigestFromBytes(bytes) };\n\t\t},\n});\n\n/**\n * The *extra* simulate fields {@link transactionResponse} can fetch. `effects` is\n * always included (this analyzer and its dependents rely on it), so it's omitted\n * here and can't be turned off — `Include` only ever widens what's fetched.\n */\ntype SimulateExtraInclude = Omit<SuiClientTypes.SimulateTransactionInclude, 'effects'>;\n\n/**\n * {@link transactionResponse}'s request-scoped options for a given extra-`Include`.\n * `transactionResponse` and `include` are mutually exclusive *in effect*: injecting a\n * pre-computed response skips the dry-run, so `include` (which only shapes a\n * simulation) is ignored — inject one or the other, not both. When simulating,\n * `include` is required exactly when `Include` names a field that must be present (so\n * a dependent that needs, say, `balanceChanges` forces it to be passed). `effects` is\n * always added on top either way.\n *\n * The exclusivity can't be a type-level union here: the analyzer framework merges a\n * dependency's options with `UnionToIntersection`, which would collapse the two\n * branches to `never` and break every dependent. So both stay optional and the\n * precedence is enforced at runtime.\n */\ntype TransactionResponseOptions<Include extends SimulateExtraInclude> = {\n\tclient: ClientWithCoreApi;\n\t/**\n\t * Inject a pre-computed response to skip the dry-run entirely (e.g. a host that\n\t * already simulated). Must carry at least the requested fields. Takes precedence\n\t * over `include` — providing both ignores `include`.\n\t */\n\ttransactionResponse?: SuiClientTypes.Transaction<Include & { effects: true }>;\n} & ({} extends Include ? { include?: Include } : { include: Include });\n\n// One shared instance — the dry-run logic lives here, once. `transactionResponse()`\n// hands this exact instance back, retyped per `Include`, so every consumer keeps the\n// same identity and `cacheKey` (deduped to a single simulation per run) instead of\n// each spinning up a copy. The runtime reads `include` off the shared options, so the\n// data fetched always matches what the call actually requested.\nconst transactionResponseAnalyzer = createAnalyzer({\n\tcacheKey: 'transactionResponse@1.0.0',\n\tdependencies: { bytes },\n\tanalyze:\n\t\t(options: TransactionResponseOptions<SimulateExtraInclude>) =>\n\t\tasync ({ bytes }): Promise<AnalyzerOutput<SuiClientTypes.Transaction<{ effects: true }>>> => {\n\t\t\t// An injected response skips the dry-run — `include` doesn't apply (it only\n\t\t\t// shapes a simulation), which is why the two are mutually exclusive.\n\t\t\tif (options.transactionResponse) {\n\t\t\t\treturn { result: options.transactionResponse };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst result = await options.client.core.simulateTransaction({\n\t\t\t\t\ttransaction: bytes,\n\t\t\t\t\t// `effects` is forced last so a caller-supplied `include` can only add to\n\t\t\t\t\t// it, never drop the effects that `simulationSucceeds` (and others) read.\n\t\t\t\t\tinclude: { ...options.include, effects: true },\n\t\t\t\t});\n\t\t\t\treturn {\n\t\t\t\t\tresult: result.Transaction ?? result.FailedTransaction,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\t// Simulation throws for many reasons (object/version resolution, gas\n\t\t\t\t// estimation, an unreachable node) — surface the underlying detail rather\n\t\t\t\t// than a generic message, and attach the error for programmatic inspection.\n\t\t\t\treturn {\n\t\t\t\t\tissues: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmessage: `Failed to dry run transaction: ${(error as Error).message}`,\n\t\t\t\t\t\t\terror: error as Error,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t}\n\t\t},\n});\n\n/**\n * The dry-run analyzer, generic over the *extra* simulate `include` fields. Calling\n * it returns the one shared analyzer instance (above) retyped for `Include`, so its\n * result exposes exactly the fields you asked for and `include` becomes a required\n * option when `Include` names one — all without duplicating the analyzer or running\n * the simulation more than once. `effects` is always included.\n *\n * ```ts\n * // Reusable, deduped, and typed to what you requested:\n * createAnalyzer({\n *   dependencies: { tx: transactionResponse<{ balanceChanges: true }>() },\n *   analyze: () => ({ tx }) => ({ result: tx.balanceChanges }), // typed `BalanceChange[]`\n * });\n * ```\n */\nexport function transactionResponse<Include extends SimulateExtraInclude = {}>(): Analyzer<\n\tSuiClientTypes.Transaction<Include & { effects: true }>,\n\tTransactionResponseOptions<Include>,\n\t{ bytes: Uint8Array }\n> {\n\treturn transactionResponseAnalyzer as unknown as Analyzer<\n\t\tSuiClientTypes.Transaction<Include & { effects: true }>,\n\t\tTransactionResponseOptions<Include>,\n\t\t{ bytes: Uint8Array }\n\t>;\n}\n\nexport const balanceChanges = createAnalyzer({\n\tdependencies: { transactionResponse: transactionResponse<{ balanceChanges: true }>() },\n\tanalyze:\n\t\t() =>\n\t\t({ transactionResponse }) => {\n\t\t\treturn { result: transactionResponse.balanceChanges };\n\t\t},\n});\n"],"mappings":";;;;AASA,MAAa,QAAQ,eAAe;CACnC,UAAU;CACV,UACE,SAAwC,gBACzC,YAAiD;AAChD,MAAI;AACH,UAAO,EACN,QAAQ,MAAM,YAAY,MAAM,EAAE,QAAQ,QAAQ,QAAQ,CAAC,EAC3D;WACO,OAAO;AAIf,UAAO,EACN,QAAQ,CACP;IACC,SAAS,gCAAiC,MAAgB;IACnD;IACP,CACD,EACD;;;CAGJ,CAAC;AAEF,MAAa,OAAO,eAAe;CAClC,cAAc,EAAE,OAAO;CACvB,UAAU,GAAG,aAAa;AACzB,SAAO,EAAE,QAAQ,GAAG,SAAS,EAAE;;CAEhC,CAAC;AAEF,MAAa,SAAS,eAAe;CACpC,cAAc,EAAE,OAAO;CACvB,gBAEE,EAAE,qBAAY;AACd,SAAO,EAAE,QAAQ,uBAAuB,mBAAmBA,QAAM,EAAE;;CAErE,CAAC;AAsCF,MAAM,8BAA8B,eAAe;CAClD,UAAU;CACV,cAAc,EAAE,OAAO;CACvB,UACE,YACD,OAAO,EAAE,qBAAoF;AAG5F,MAAI,QAAQ,oBACX,QAAO,EAAE,QAAQ,QAAQ,qBAAqB;AAE/C,MAAI;GACH,MAAM,SAAS,MAAM,QAAQ,OAAO,KAAK,oBAAoB;IAC5D,aAAaA;IAGb,SAAS;KAAE,GAAG,QAAQ;KAAS,SAAS;KAAM;IAC9C,CAAC;AACF,UAAO,EACN,QAAQ,OAAO,eAAe,OAAO,mBACrC;WACO,OAAO;AAIf,UAAO,EACN,QAAQ,CACP;IACC,SAAS,kCAAmC,MAAgB;IACrD;IACP,CACD,EACD;;;CAGJ,CAAC;;;;;;;;;;;;;;;;AAiBF,SAAgB,sBAId;AACD,QAAO;;AAOR,MAAa,iBAAiB,eAAe;CAC5C,cAAc,EAAE,qBAAqB,qBAA+C,EAAE;CACtF,gBAEE,EAAE,iDAA0B;AAC5B,SAAO,EAAE,QAAQC,sBAAoB,gBAAgB;;CAEvD,CAAC"}