@gearbox-protocol/sdk 14.11.0-next.5 → 14.11.0-next.7

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.
Files changed (49) hide show
  1. package/dist/cjs/preview/parse/extractExpectedBalanceChanges.js +48 -0
  2. package/dist/cjs/preview/parse/index.js +2 -0
  3. package/dist/cjs/preview/parse/parseFacadeOperationCalldata.js +12 -5
  4. package/dist/cjs/preview/parse/parsePoolOperationCalldata.js +21 -6
  5. package/dist/cjs/preview/parse/types.js +1 -1
  6. package/dist/cjs/preview/prerequisites/buildPrerequisites.js +46 -0
  7. package/dist/cjs/preview/simulate/constants.js +28 -0
  8. package/dist/cjs/preview/simulate/{decodeSimulationError.js → errors.js} +37 -3
  9. package/dist/cjs/preview/simulate/holders.js +45 -0
  10. package/dist/cjs/preview/simulate/index.js +21 -13
  11. package/dist/cjs/preview/simulate/simulateFacadeOperation.js +1 -1
  12. package/dist/cjs/preview/simulate/simulateOperation.js +3 -3
  13. package/dist/cjs/preview/simulate/simulatePoolOpMulticall.js +155 -0
  14. package/dist/cjs/preview/simulate/simulatePoolOpV1.js +106 -0
  15. package/dist/cjs/preview/simulate/simulatePoolOperation.js +27 -62
  16. package/dist/esm/preview/parse/extractExpectedBalanceChanges.js +24 -0
  17. package/dist/esm/preview/parse/index.js +1 -0
  18. package/dist/esm/preview/parse/parseFacadeOperationCalldata.js +12 -5
  19. package/dist/esm/preview/parse/parsePoolOperationCalldata.js +21 -6
  20. package/dist/esm/preview/parse/types.js +1 -1
  21. package/dist/esm/preview/prerequisites/buildPrerequisites.js +46 -0
  22. package/dist/esm/preview/simulate/constants.js +4 -0
  23. package/dist/esm/preview/simulate/{decodeSimulationError.js → errors.js} +31 -0
  24. package/dist/esm/preview/simulate/holders.js +21 -0
  25. package/dist/esm/preview/simulate/index.js +12 -6
  26. package/dist/esm/preview/simulate/simulateFacadeOperation.js +1 -1
  27. package/dist/esm/preview/simulate/simulateOperation.js +3 -3
  28. package/dist/esm/preview/simulate/simulatePoolOpMulticall.js +130 -0
  29. package/dist/esm/preview/simulate/simulatePoolOpV1.js +82 -0
  30. package/dist/esm/preview/simulate/simulatePoolOperation.js +30 -62
  31. package/dist/types/history/types.d.ts +4 -4
  32. package/dist/types/preview/parse/extractExpectedBalanceChanges.d.ts +22 -0
  33. package/dist/types/preview/parse/index.d.ts +1 -0
  34. package/dist/types/preview/parse/parsePoolOperationCalldata.d.ts +4 -2
  35. package/dist/types/preview/parse/types-facades.d.ts +33 -0
  36. package/dist/types/preview/parse/types-pools.d.ts +29 -16
  37. package/dist/types/preview/parse/types.d.ts +3 -3
  38. package/dist/types/preview/simulate/constants.d.ts +6 -0
  39. package/dist/types/preview/simulate/errors.d.ts +51 -0
  40. package/dist/types/preview/simulate/holders.d.ts +7 -0
  41. package/dist/types/preview/simulate/index.d.ts +9 -6
  42. package/dist/types/preview/simulate/simulateFacadeOperation.d.ts +3 -5
  43. package/dist/types/preview/simulate/simulateOperation.d.ts +5 -11
  44. package/dist/types/preview/simulate/simulatePoolOpMulticall.d.ts +28 -0
  45. package/dist/types/preview/simulate/simulatePoolOpV1.d.ts +14 -0
  46. package/dist/types/preview/simulate/simulatePoolOperation.d.ts +5 -27
  47. package/dist/types/preview/simulate/types.d.ts +54 -18
  48. package/package.json +1 -1
  49. package/dist/types/preview/simulate/decodeSimulationError.d.ts +0 -18
@@ -0,0 +1,82 @@
1
+ import { simulateCalls } from "viem/actions";
2
+ import { ierc20Abi } from "../../abi/iERC20.js";
3
+ import { decodeSimulationError, PreviewSimulationError } from "./errors.js";
4
+ import { extractERC20Transfers } from "./extractERC20Transfers.js";
5
+ import { watchedHolders } from "./holders.js";
6
+ async function simulatePoolOpV1(input, options = {}) {
7
+ const { sdk, operation, to, calldata, wallet } = input;
8
+ const { blockNumber } = options;
9
+ const { underlying, pool } = operation;
10
+ const holders = watchedHolders(operation, wallet);
11
+ const tokens = [underlying, pool];
12
+ const balanceOf = (token, holder) => ({
13
+ to: token,
14
+ abi: ierc20Abi,
15
+ functionName: "balanceOf",
16
+ args: [holder]
17
+ });
18
+ const balanceCalls = holders.flatMap(
19
+ (holder) => tokens.map((token) => balanceOf(token, holder))
20
+ );
21
+ let results;
22
+ try {
23
+ ({ results } = await simulateCalls(sdk.client, {
24
+ account: wallet,
25
+ // `undefined` lets viem simulate at `latest`; `blockNumber` is only set
26
+ // for testnet forks pinned to a specific block.
27
+ blockNumber,
28
+ calls: [...balanceCalls, { to, data: calldata }, ...balanceCalls]
29
+ }));
30
+ } catch (cause) {
31
+ throw new PreviewSimulationError([
32
+ {
33
+ source: "eth_simulateV1",
34
+ detail: decodeSimulationError({
35
+ error: cause instanceof Error ? cause : new Error(String(cause))
36
+ })
37
+ }
38
+ ]);
39
+ }
40
+ const sim = results;
41
+ const txIndex = balanceCalls.length;
42
+ const afterOffset = txIndex + 1;
43
+ const txResult = sim[txIndex];
44
+ if (!txResult || txResult.status === "failure") {
45
+ throw new PreviewSimulationError([
46
+ {
47
+ source: "eth_simulateV1",
48
+ detail: decodeSimulationError({
49
+ error: txResult?.error,
50
+ data: txResult?.data
51
+ })
52
+ }
53
+ ]);
54
+ }
55
+ const balanceChanges = [];
56
+ for (const [holderIndex, address] of holders.entries()) {
57
+ const changes = [];
58
+ for (const [tokenIndex, token] of tokens.entries()) {
59
+ const slot = holderIndex * tokens.length + tokenIndex;
60
+ const before = readBalance(sim[slot]);
61
+ const after = readBalance(sim[afterOffset + slot]);
62
+ const delta = after - before;
63
+ const magnitude = delta >= 0n ? delta : -delta;
64
+ if (magnitude > 1n) {
65
+ changes.push({ token, before, after, delta });
66
+ }
67
+ }
68
+ if (changes.length > 0) {
69
+ balanceChanges.push({ address, changes });
70
+ }
71
+ }
72
+ return {
73
+ transfers: extractERC20Transfers(txResult.logs ?? [], holders),
74
+ balanceChanges
75
+ };
76
+ }
77
+ function readBalance(result) {
78
+ return result?.status === "success" ? result.result : 0n;
79
+ }
80
+ export {
81
+ simulatePoolOpV1
82
+ };
@@ -1,69 +1,37 @@
1
- import { isAddressEqual } from "viem";
2
- import { simulateCalls } from "viem/actions";
3
- import { ierc20Abi } from "../../abi/iERC20.js";
4
- import { decodeSimulationError } from "./decodeSimulationError.js";
5
- import { extractERC20Transfers } from "./extractERC20Transfers.js";
6
- async function simulatePoolOperation(input) {
7
- const { sdk, operation, to, calldata, wallet, blockNumber } = input;
8
- const { underlying, pool } = operation;
9
- const receiverIsWallet = isAddressEqual(operation.receiver, wallet);
10
- const holders = receiverIsWallet ? [wallet] : [wallet, operation.receiver];
11
- const tokens = [underlying, pool];
12
- const balanceOf = (token, holder) => ({
13
- to: token,
14
- abi: ierc20Abi,
15
- functionName: "balanceOf",
16
- args: [holder]
17
- });
18
- const balanceCalls = holders.flatMap(
19
- (holder) => tokens.map((token) => balanceOf(token, holder))
1
+ import {
2
+ asPreviewSimulationError,
3
+ combinePreviewSimulationErrors
4
+ } from "./errors.js";
5
+ import { simulatePoolOpMulticall } from "./simulatePoolOpMulticall.js";
6
+ import { simulatePoolOpV1 } from "./simulatePoolOpV1.js";
7
+ async function simulatePoolOperation(input, options = {}) {
8
+ const { logger, useSimulateV1 } = options;
9
+ logger?.debug(
10
+ { wallet: input.wallet, to: input.to },
11
+ "simulating pool operation"
20
12
  );
21
- const { results } = await simulateCalls(sdk.client, {
22
- account: wallet,
23
- // `undefined` lets viem simulate at `latest`; `blockNumber` is only set for
24
- // testnet forks pinned to a specific block.
25
- blockNumber,
26
- calls: [...balanceCalls, { to, data: calldata }, ...balanceCalls]
27
- });
28
- const sim = results;
29
- const txIndex = balanceCalls.length;
30
- const afterOffset = txIndex + 1;
31
- const txResult = sim[txIndex];
32
- if (!txResult || txResult.status === "failure") {
33
- return {
34
- status: "failure",
35
- error: decodeSimulationError({
36
- error: txResult?.error,
37
- data: txResult?.data
38
- })
39
- };
13
+ const [v1, multicall] = await Promise.allSettled([
14
+ useSimulateV1 ? simulatePoolOpV1(input, options) : void 0,
15
+ simulatePoolOpMulticall(input, options)
16
+ ]);
17
+ if (v1.status === "fulfilled" && v1.value) {
18
+ return { status: "success", ...v1.value };
40
19
  }
41
- const balanceChanges = [];
42
- for (const [holderIndex, address] of holders.entries()) {
43
- const changes = [];
44
- for (const [tokenIndex, token] of tokens.entries()) {
45
- const slot = holderIndex * tokens.length + tokenIndex;
46
- const before = readBalance(sim[slot]);
47
- const after = readBalance(sim[afterOffset + slot]);
48
- const delta = after - before;
49
- const magnitude = delta >= 0n ? delta : -delta;
50
- if (magnitude > 1n) {
51
- changes.push({ token, before, after, delta });
52
- }
53
- }
54
- if (changes.length > 0) {
55
- balanceChanges.push({ address, changes });
20
+ if (multicall.status === "fulfilled") {
21
+ if (v1.status === "rejected") {
22
+ logger?.debug(
23
+ asPreviewSimulationError(v1.reason, "eth_simulateV1"),
24
+ "eth_simulateV1 flow failed; falling back to multicall result"
25
+ );
56
26
  }
27
+ return { status: "success", ...multicall.value };
57
28
  }
58
- return {
59
- status: "success",
60
- transfers: extractERC20Transfers(txResult.logs ?? [], holders),
61
- balanceChanges,
62
- gasUsed: txResult.gasUsed
63
- };
64
- }
65
- function readBalance(result) {
66
- return result?.status === "success" ? result.result : 0n;
29
+ const error = combinePreviewSimulationErrors(
30
+ v1.status === "rejected" ? asPreviewSimulationError(v1.reason, "eth_simulateV1") : void 0,
31
+ asPreviewSimulationError(multicall.reason, "multicall")
32
+ );
33
+ logger?.error(error, "pool operation simulation failed");
34
+ return { status: "failure", error };
67
35
  }
68
36
  export {
69
37
  simulatePoolOperation
@@ -18,10 +18,10 @@ export type HistoryAdapterExt = TraceAdapterExt & {
18
18
  export type HistoryFacadeMetadata = FacadeOperationMetadata & OperationMetadata;
19
19
  export type AdapterOperation = BaseAdapterOperation<HistoryAdapterExt>;
20
20
  export type InnerOperation = BaseInnerOperation<HistoryAdapterExt>;
21
- export type MulticallOperation = BaseMulticallOperation<HistoryAdapterExt> & OperationMetadata;
22
- export type OpenCreditAccountOperation = BaseOpenCreditAccountOperation<HistoryAdapterExt> & OperationMetadata;
23
- export type CloseCreditAccountOperation = BaseCloseCreditAccountOperation<HistoryAdapterExt> & OperationMetadata;
24
- export type LiquidateCreditAccountOperation = BaseLiquidateCreditAccountOperation<HistoryAdapterExt> & OperationMetadata;
21
+ export type MulticallOperation = Omit<BaseMulticallOperation<HistoryAdapterExt>, "expectedBalanceChanges"> & OperationMetadata;
22
+ export type OpenCreditAccountOperation = Omit<BaseOpenCreditAccountOperation<HistoryAdapterExt>, "expectedBalanceChanges"> & OperationMetadata;
23
+ export type CloseCreditAccountOperation = Omit<BaseCloseCreditAccountOperation<HistoryAdapterExt>, "expectedBalanceChanges"> & OperationMetadata;
24
+ export type LiquidateCreditAccountOperation = Omit<BaseLiquidateCreditAccountOperation<HistoryAdapterExt>, "expectedBalanceChanges"> & OperationMetadata;
25
25
  export type PartialLiquidationOperation = BasePartialLiquidationOperation & OperationMetadata;
26
26
  export type DirectTokenTransferOperation = BaseDirectTokenTransferOperation & OperationMetadata;
27
27
  export type OuterFacadeOperation = MulticallOperation | OpenCreditAccountOperation | CloseCreditAccountOperation | LiquidateCreditAccountOperation | PartialLiquidationOperation;
@@ -0,0 +1,22 @@
1
+ import type { ParsedCallV2 } from "../../sdk/index.js";
2
+ import type { ExpectedBalanceChange } from "./types.js";
3
+ /**
4
+ * Recovers the potential balance changes declared by a router-generated
5
+ * `storeExpectedBalances`/`compareBalances` pair inside a credit-facade
6
+ * multicall.
7
+ *
8
+ * The detection is intentionally limited to the router shape:
9
+ * - `onDemandPriceUpdates` calls are dropped first (they may only appear at the
10
+ * front of a multicall);
11
+ * - the remaining calls must start with `storeExpectedBalances` and end with
12
+ * `compareBalances`.
13
+ *
14
+ * When the multicall does not match this shape, `undefined` is returned. On a
15
+ * match, the `BalanceDelta[]` argument of `storeExpectedBalances` is decoded
16
+ * into {@link ExpectedBalanceChange}[] (the `amount` is the signed `int256`
17
+ * delta and may be negative).
18
+ *
19
+ * @param innerCalls - Raw (already-decoded) inner multicall calls.
20
+ * @returns The declared balance changes, or `undefined` when not router-shaped.
21
+ */
22
+ export declare function extractExpectedBalanceChanges(innerCalls: ParsedCallV2[]): ExpectedBalanceChange[] | undefined;
@@ -1,5 +1,6 @@
1
1
  export * from "./classifyInnerOperations.js";
2
2
  export * from "./errors.js";
3
+ export * from "./extractExpectedBalanceChanges.js";
3
4
  export * from "./parseFacadeOperationCalldata.js";
4
5
  export * from "./parseOperationCalldata.js";
5
6
  export * from "./parsePoolOperationCalldata.js";
@@ -8,8 +8,10 @@ export interface ParsePoolOperationCalldataProps {
8
8
  calldata: Hex;
9
9
  }
10
10
  /**
11
- * Decodes ERC4626 `deposit`/`depositWithReferral`/`redeem` calldata on a
12
- * Gearbox pool into a {@link PoolOperation}. Any other selector throws
11
+ * Decodes ERC4626 pool calldata into a {@link PoolOperation}. Supports every
12
+ * deposit/mint/withdraw/redeem variant of `IPoolV3` (and the `IERC4626` base it
13
+ * extends): `deposit`/`depositWithReferral`, `mint`/`mintWithReferral`,
14
+ * `withdraw` and `redeem`. Any other selector throws
13
15
  * {@link UnsupportedPoolFunctionError}.
14
16
  */
15
17
  export declare function parsePoolOperationCalldata(props: ParsePoolOperationCalldataProps): PoolOperation;
@@ -71,10 +71,25 @@ export interface FacadeOperationMetadata {
71
71
  creditManager: Address;
72
72
  creditFacade: Address;
73
73
  }
74
+ /**
75
+ * Signed token balance delta recovered from a router-generated
76
+ * `storeExpectedBalances` call (the `BalanceDelta` struct). `amount` is the
77
+ * signed `int256` delta, so it may be negative.
78
+ */
79
+ export interface ExpectedBalanceChange {
80
+ token: Address;
81
+ delta: bigint;
82
+ }
74
83
  export interface MulticallOperation<Ext extends object = {}> extends FacadeOperationMetadata {
75
84
  operation: "MultiCall" | "BotMulticall";
76
85
  creditAccount: Address;
77
86
  multicall: InnerOperation<Ext>[];
87
+ /**
88
+ * Potential balance changes declared by a router-generated
89
+ * `storeExpectedBalances`/`compareBalances` pair, or `undefined` when the
90
+ * multicall is not router-shaped. See {@link ExpectedBalanceChange}.
91
+ */
92
+ expectedBalanceChanges?: ExpectedBalanceChange[];
78
93
  }
79
94
  export interface OpenCreditAccountOperation<Ext extends object = {}> extends FacadeOperationMetadata {
80
95
  operation: "OpenCreditAccount";
@@ -82,11 +97,23 @@ export interface OpenCreditAccountOperation<Ext extends object = {}> extends Fac
82
97
  onBehalfOf: Address;
83
98
  referralCode: bigint;
84
99
  multicall: InnerOperation<Ext>[];
100
+ /**
101
+ * Potential balance changes declared by a router-generated
102
+ * `storeExpectedBalances`/`compareBalances` pair, or `undefined` when the
103
+ * multicall is not router-shaped. See {@link ExpectedBalanceChange}.
104
+ */
105
+ expectedBalanceChanges?: ExpectedBalanceChange[];
85
106
  }
86
107
  export interface CloseCreditAccountOperation<Ext extends object = {}> extends FacadeOperationMetadata {
87
108
  operation: "CloseCreditAccount";
88
109
  creditAccount: Address;
89
110
  multicall: InnerOperation<Ext>[];
111
+ /**
112
+ * Potential balance changes declared by a router-generated
113
+ * `storeExpectedBalances`/`compareBalances` pair, or `undefined` when the
114
+ * multicall is not router-shaped. See {@link ExpectedBalanceChange}.
115
+ */
116
+ expectedBalanceChanges?: ExpectedBalanceChange[];
90
117
  }
91
118
  export interface LiquidateCreditAccountOperation<Ext extends object = {}> extends FacadeOperationMetadata {
92
119
  operation: "LiquidateCreditAccount";
@@ -95,6 +122,12 @@ export interface LiquidateCreditAccountOperation<Ext extends object = {}> extend
95
122
  token: Address;
96
123
  remainingFunds: bigint;
97
124
  multicall: InnerOperation<Ext>[];
125
+ /**
126
+ * Potential balance changes declared by a router-generated
127
+ * `storeExpectedBalances`/`compareBalances` pair, or `undefined` when the
128
+ * multicall is not router-shaped. See {@link ExpectedBalanceChange}.
129
+ */
130
+ expectedBalanceChanges?: ExpectedBalanceChange[];
98
131
  }
99
132
  export interface PartialLiquidationOperation extends FacadeOperationMetadata {
100
133
  operation: "PartiallyLiquidateCreditAccount";
@@ -1,9 +1,6 @@
1
1
  import type { Address } from "viem";
2
- import type { TokenTransfer } from "./types-adapters.js";
3
2
  /**
4
3
  * ERC4626 `deposit` into a Gearbox pool.
5
- * Token metadata (symbol/decimals) is intentionally omitted: consumers resolve
6
- * it from `sdk.tokensMeta` using the token addresses below.
7
4
  */
8
5
  export interface PoolDepositOperation {
9
6
  operation: "Deposit";
@@ -14,16 +11,37 @@ export interface PoolDepositOperation {
14
11
  underlying: Address;
15
12
  /** Referral code, present only for `depositWithReferral` calls. */
16
13
  referralCode?: bigint;
17
- /**
18
- * ERC-20 transfers involving the wallet, recovered by simulating the call.
19
- * Empty for the calldata-only parse; populated by the simulation stage.
20
- */
21
- transfers: TokenTransfer[];
14
+ }
15
+ /**
16
+ * ERC4626 `mint` into a Gearbox pool. Unlike `deposit`, the caller specifies the
17
+ * amount of shares to mint; the assets pulled are resolved by the pool.
18
+ */
19
+ export interface PoolMintOperation {
20
+ operation: "Mint";
21
+ pool: Address;
22
+ receiver: Address;
23
+ /** Pool shares (diesel) minted to the receiver. */
24
+ shares: bigint;
25
+ underlying: Address;
26
+ /** Referral code, present only for `mintWithReferral` calls. */
27
+ referralCode?: bigint;
28
+ }
29
+ /**
30
+ * ERC4626 `withdraw` from a Gearbox pool. Unlike `redeem`, the caller specifies
31
+ * the amount of underlying assets to withdraw; the shares burned are resolved by
32
+ * the pool.
33
+ */
34
+ export interface PoolWithdrawOperation {
35
+ operation: "Withdraw";
36
+ pool: Address;
37
+ receiver: Address;
38
+ owner: Address;
39
+ /** Underlying assets withdrawn to the receiver. */
40
+ assets: bigint;
41
+ underlying: Address;
22
42
  }
23
43
  /**
24
44
  * ERC4626 `redeem` from a Gearbox pool.
25
- * Token metadata (symbol/decimals) is intentionally omitted: consumers resolve
26
- * it from `sdk.tokensMeta` using the token addresses below.
27
45
  */
28
46
  export interface PoolRedeemOperation {
29
47
  operation: "Redeem";
@@ -33,10 +51,5 @@ export interface PoolRedeemOperation {
33
51
  /** Pool shares (diesel) burned. */
34
52
  shares: bigint;
35
53
  underlying: Address;
36
- /**
37
- * ERC-20 transfers involving the wallet, recovered by simulating the call.
38
- * Empty for the calldata-only parse; populated by the simulation stage.
39
- */
40
- transfers: TokenTransfer[];
41
54
  }
42
- export type PoolOperation = PoolDepositOperation | PoolRedeemOperation;
55
+ export type PoolOperation = PoolDepositOperation | PoolMintOperation | PoolWithdrawOperation | PoolRedeemOperation;
@@ -37,8 +37,8 @@ export type SdkWithAdapters<P extends PluginsMap = PluginsMap> = OnchainSDK<P> &
37
37
  */
38
38
  export type Operation = PoolOperation | OuterFacadeOperation;
39
39
  /**
40
- * Narrows an {@link Operation} to a {@link PoolOperation} (deposit or redeem).
41
- * Used by the UI to decide whether a custom view exists for the parsed result;
42
- * everything else falls back to the raw JSON view.
40
+ * Narrows an {@link Operation} to a {@link PoolOperation} (deposit, mint,
41
+ * withdraw or redeem). Used by the UI to decide whether a custom view exists for
42
+ * the parsed result; everything else falls back to the raw JSON view.
43
43
  */
44
44
  export declare function isPoolOperation(tx: Operation): tx is PoolOperation;
@@ -0,0 +1,6 @@
1
+ import type { NetworkType } from "../../sdk/chain/index.js";
2
+ /**
3
+ * Networks where the `eth_simulateV1` JSON-RPC method is available and usable
4
+ * for pool or credit account operation simulation.
5
+ **/
6
+ export declare const ETH_SIMULATE_V1_NETWORKS: ReadonlySet<NetworkType>;
@@ -0,0 +1,51 @@
1
+ import { BaseError, type Hex } from "viem";
2
+ /** Which simulation flow produced a failure. */
3
+ export type SimulationFlowSource = "eth_simulateV1" | "multicall" | "unknown";
4
+ /** A single flow failure with its decoded revert detail. */
5
+ export interface SimulationFlowFailure {
6
+ source: SimulationFlowSource;
7
+ detail: SimulationError;
8
+ }
9
+ /**
10
+ * Error returned by the pool simulation when all attempted flows fail.
11
+ *
12
+ * On a single-flow failure it wraps that flow's decoded revert reason; when both
13
+ * the `eth_simulateV1` and multicall flows fail, it carries the details of both
14
+ * (see {@link failures}).
15
+ */
16
+ export declare class PreviewSimulationError extends BaseError {
17
+ name: string;
18
+ /** Per-flow decoded failures behind this error. */
19
+ readonly failures: SimulationFlowFailure[];
20
+ constructor(failures: SimulationFlowFailure[]);
21
+ }
22
+ /**
23
+ * Normalises an unknown rejection reason into a {@link PreviewSimulationError}.
24
+ * Pass-through when it already is one; otherwise decodes it under `source`.
25
+ */
26
+ export declare function asPreviewSimulationError(reason: unknown, source: SimulationFlowSource): PreviewSimulationError;
27
+ /** Merges several {@link PreviewSimulationError}s into one carrying all failures. */
28
+ export declare function combinePreviewSimulationErrors(...errors: (PreviewSimulationError | undefined)[]): PreviewSimulationError;
29
+ /** Decoded revert of the simulated transaction. */
30
+ export interface SimulationError {
31
+ /** Human-readable revert reason / error name. */
32
+ reason: string;
33
+ /** Original error, kept for debugging. */
34
+ cause?: unknown;
35
+ }
36
+ /** Per-call slice of a `simulateCalls` failure we need to decode. */
37
+ export interface SimulationRevert {
38
+ error?: Error;
39
+ /** Raw revert return data, when present. */
40
+ data?: Hex;
41
+ }
42
+ /**
43
+ * Decodes a simulated transaction revert into a {@link SimulationError}.
44
+ *
45
+ * The simulated call is raw calldata (no ABI), so viem cannot decode the revert
46
+ * itself. We first try to decode the raw return bytes against the SDK's
47
+ * {@link errorAbis} (Gearbox protocol exceptions plus standard ERC-20 custom
48
+ * errors); failing that, we walk viem's error chain for a
49
+ * {@link ContractFunctionRevertedError} (covers `Error(string)` / `Panic`).
50
+ */
51
+ export declare function decodeSimulationError(revert: SimulationRevert): SimulationError;
@@ -0,0 +1,7 @@
1
+ import type { Address } from "viem";
2
+ import type { PoolOperation } from "../parse/index.js";
3
+ /**
4
+ * Distinct addresses whose balances change during the operation: the funds
5
+ * source (payer or share owner) and the receiver.
6
+ */
7
+ export declare function watchedHolders(operation: PoolOperation, wallet: Address): Address[];
@@ -1,6 +1,9 @@
1
- export * from "./decodeSimulationError.js";
2
- export * from "./extractERC20Transfers.js";
3
- export * from "./simulateFacadeOperation.js";
4
- export * from "./simulateOperation.js";
5
- export * from "./simulatePoolOperation.js";
6
- export * from "./types.js";
1
+ export { ETH_SIMULATE_V1_NETWORKS } from "./constants.js";
2
+ export type { SimulationError, SimulationFlowFailure, SimulationFlowSource, } from "./errors.js";
3
+ export { PreviewSimulationError } from "./errors.js";
4
+ export type { SimulateFacadeOperationInput } from "./simulateFacadeOperation.js";
5
+ export { simulateFacadeOperation } from "./simulateFacadeOperation.js";
6
+ export type { SimulateOperationInput } from "./simulateOperation.js";
7
+ export { simulateOperation } from "./simulateOperation.js";
8
+ export { simulatePoolOperation } from "./simulatePoolOperation.js";
9
+ export type { AddressBalanceChanges, OperationSimulationOptions, PoolOperationSimulation, PoolOperationSimulationInput, PoolOperationSimulationResult, TokenBalanceChange, } from "./types.js";
@@ -1,9 +1,9 @@
1
1
  import type { Address, Hex } from "viem";
2
2
  import type { OnchainSDK } from "../../sdk/index.js";
3
3
  import type { OuterFacadeOperation } from "../parse/index.js";
4
- import type { PoolSimulationResult } from "./types.js";
4
+ import type { OperationSimulationOptions, PoolOperationSimulation } from "./types.js";
5
5
  export interface SimulateFacadeOperationInput {
6
- /** Only `client` is used, so any OnchainSDK works. */
6
+ /** Only `client`/`networkType` are used, so any OnchainSDK works. */
7
7
  sdk: OnchainSDK;
8
8
  /** Parsed credit-facade operation to simulate. */
9
9
  operation: OuterFacadeOperation;
@@ -13,8 +13,6 @@ export interface SimulateFacadeOperationInput {
13
13
  calldata: Hex;
14
14
  /** Wallet whose balance changes and transfers we track. */
15
15
  wallet: Address;
16
- /** Block to simulate at; defaults to latest. Only set for testnet forks. */
17
- blockNumber?: bigint;
18
16
  }
19
17
  /**
20
18
  * Simulates a credit-facade operation.
@@ -24,4 +22,4 @@ export interface SimulateFacadeOperationInput {
24
22
  * signature mirrors {@link simulatePoolOperation} so the
25
23
  * {@link simulateOperation} wrapper can delegate uniformly once implemented.
26
24
  */
27
- export declare function simulateFacadeOperation(_input: SimulateFacadeOperationInput): Promise<PoolSimulationResult>;
25
+ export declare function simulateFacadeOperation(_input: SimulateFacadeOperationInput, _options?: OperationSimulationOptions): Promise<PoolOperationSimulation>;
@@ -1,11 +1,11 @@
1
1
  import type { Address, Hex } from "viem";
2
2
  import type { OnchainSDK } from "../../sdk/index.js";
3
3
  import { type Operation } from "../parse/index.js";
4
- import type { PoolSimulationResult } from "./types.js";
4
+ import type { OperationSimulationOptions, PoolOperationSimulation } from "./types.js";
5
5
  export interface SimulateOperationInput {
6
- /** Only `client` is used, so any OnchainSDK works. */
6
+ /** Gearbox SDK instance. */
7
7
  sdk: OnchainSDK;
8
- /** Parsed operation, used to route to the matching simulation. */
8
+ /** Parsed pool or credit account operation */
9
9
  operation: Operation;
10
10
  /** Target contract the calldata is sent to. */
11
11
  to: Address;
@@ -13,14 +13,8 @@ export interface SimulateOperationInput {
13
13
  calldata: Hex;
14
14
  /** Wallet whose balance changes and transfers we track. */
15
15
  wallet: Address;
16
- /** Block to simulate at; defaults to latest. Only set for testnet forks. */
17
- blockNumber?: bigint;
18
16
  }
19
17
  /**
20
- * Simulates a parsed {@link Operation} by delegating to the matching simulator:
21
- * pool deposit/redeem operations go to {@link simulatePoolOperation}, and
22
- * credit-facade operations go to {@link simulateFacadeOperation} (currently a
23
- * stub). Returns the recovered transfers, balance changes and gas on success,
24
- * or a decoded revert on failure.
18
+ * Simulates a parsed pool or credit account operation {@link Operation}
25
19
  */
26
- export declare function simulateOperation(input: SimulateOperationInput): Promise<PoolSimulationResult>;
20
+ export declare function simulateOperation(input: SimulateOperationInput, options?: OperationSimulationOptions): Promise<PoolOperationSimulation>;
@@ -0,0 +1,28 @@
1
+ import type { Address } from "viem";
2
+ import type { PoolOperation } from "../parse/index.js";
3
+ import type { AddressBalanceChanges, OperationSimulationOptions, PoolOperationSimulationInput, PoolOperationSimulationResult } from "./types.js";
4
+ /** Reads a watched holder's "before" balance of a token. */
5
+ export type BalanceLookup = (token: Address, holder: Address) => bigint;
6
+ /**
7
+ * Multicall pool-operation flow, used where `eth_simulateV1` is unavailable or
8
+ * as a fallback alongside it.
9
+ *
10
+ * Reads the watched holders' "before" balances together with the matching
11
+ * ERC4626 preview (`previewDeposit`/`previewMint`/`previewWithdraw`/
12
+ * `previewRedeem`) in a single multicall, then computes the theoretical balance
13
+ * changes via {@link computePoolOpBalanceChanges}.
14
+ *
15
+ * Unlike the `eth_simulateV1` flow it does not execute the calldata, so it
16
+ * cannot recover ERC-20 transfers (`transfers` is always `undefined`) and it
17
+ * ignores balance/allowance prerequisites (preview reads succeed regardless).
18
+ *
19
+ * @throws {@link PreviewSimulationError} when the multicall round-trip throws or
20
+ * any call (a balance read or the preview read) reverts.
21
+ */
22
+ export declare function simulatePoolOpMulticall(input: PoolOperationSimulationInput, options?: OperationSimulationOptions): Promise<PoolOperationSimulationResult>;
23
+ /**
24
+ * Pure computation of {@link AddressBalanceChanges} for a pool operation from
25
+ * its ERC4626 preview result and the watched holders' "before" balances. Legs
26
+ * sharing the same address are grouped together.
27
+ */
28
+ export declare function computePoolOpBalanceChanges(operation: PoolOperation, wallet: Address, previewAmount: bigint, before: BalanceLookup): AddressBalanceChanges[];
@@ -0,0 +1,14 @@
1
+ import type { OperationSimulationOptions, PoolOperationSimulationInput, PoolOperationSimulationResult } from "./types.js";
2
+ /**
3
+ * `eth_simulateV1` pool-operation flow.
4
+ *
5
+ * Sandwiches the raw calldata between `balanceOf` reads of the underlying and
6
+ * pool (share) tokens for every watched holder, then derives the balance changes
7
+ * from the before/after diff and the wallet-relevant ERC-20 transfers from the
8
+ * emitted logs. Simulation runs against real chain state (no overrides), so an
9
+ * unmet prerequisite surfaces here as a revert.
10
+ *
11
+ * @throws {@link PreviewSimulationError} when the round-trip throws or the
12
+ * simulated transaction reverts.
13
+ */
14
+ export declare function simulatePoolOpV1(input: PoolOperationSimulationInput, options?: OperationSimulationOptions): Promise<PoolOperationSimulationResult>;
@@ -1,30 +1,8 @@
1
- import { type Address, type Hex } from "viem";
2
- import type { OnchainSDK } from "../../sdk/index.js";
3
- import type { PoolOperation } from "../parse/index.js";
4
- import type { PoolSimulationResult } from "./types.js";
5
- export interface SimulatePoolOperationInput {
6
- /** Only `client` is used, so any OnchainSDK works. */
7
- sdk: OnchainSDK;
8
- /** Parsed operation, used to resolve the underlying and pool tokens. */
9
- operation: PoolOperation;
10
- /** Target contract the calldata is sent to (the pool). */
11
- to: Address;
12
- /** Raw deposit/redeem calldata to simulate. */
13
- calldata: Hex;
14
- /** Wallet whose balance changes and transfers we track. */
15
- wallet: Address;
16
- /** Block to simulate at; defaults to latest. Only set for testnet forks. */
17
- blockNumber?: bigint;
18
- }
1
+ import type { OperationSimulationOptions, PoolOperationSimulation, PoolOperationSimulationInput } from "./types.js";
19
2
  /**
20
- * Simulates a pool deposit/redeem by sandwiching the raw calldata between
21
- * `balanceOf(wallet)` reads of the underlying and pool (share) tokens.
3
+ * Simulates a pool deposit/mint/withdraw/redeem and returns the resulting
4
+ * balance changes (and, when available, ERC-20 transfers), or a decoded failure.
22
5
  *
23
- * On success, returns the ERC-20 transfers emitted by the call that involve the
24
- * wallet or the operation recipient (for merging into the parsed operation) and
25
- * the balance changes grouped by watched address (wallet, plus the recipient
26
- * when distinct); on revert, returns the decoded reason. Simulation runs against
27
- * real chain state (no overrides), so an unmet prerequisite surfaces here as a
28
- * failure.
6
+ * @throws {@link PreviewSimulationError} when the simulation fails.
29
7
  */
30
- export declare function simulatePoolOperation(input: SimulatePoolOperationInput): Promise<PoolSimulationResult>;
8
+ export declare function simulatePoolOperation(input: PoolOperationSimulationInput, options?: OperationSimulationOptions): Promise<PoolOperationSimulation>;