@gearbox-protocol/sdk 14.11.3 → 14.12.0-next.1

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 (180) hide show
  1. package/dist/cjs/common-utils/utils/index.js +2 -0
  2. package/dist/cjs/{history/trace-utils.js → common-utils/utils/trace.js} +62 -5
  3. package/dist/cjs/dev/index.js +3 -1
  4. package/dist/cjs/dev/verifyTestnet.js +52 -0
  5. package/dist/cjs/history/assembleOperations.js +6 -6
  6. package/dist/cjs/history/classifyMulticallOperations.js +31 -25
  7. package/dist/cjs/history/index.js +0 -2
  8. package/dist/cjs/history/parseCreditAccountTransaction.js +5 -6
  9. package/dist/cjs/history/toLegacyOperation.js +5 -1
  10. package/dist/cjs/plugins/adapters/contracts/AbstractAdapter.js +25 -37
  11. package/dist/cjs/plugins/adapters/contracts/AccountMigratorAdapterContract.js +9 -0
  12. package/dist/cjs/{history/internal-types.js → plugins/adapters/transfers.js} +2 -2
  13. package/dist/cjs/preview/index.js +28 -0
  14. package/dist/cjs/preview/package.json +1 -0
  15. package/dist/cjs/preview/parse/classifyInnerOperations.js +92 -0
  16. package/dist/cjs/preview/parse/errors.js +47 -0
  17. package/dist/cjs/preview/parse/extractExpectedBalanceChanges.js +48 -0
  18. package/dist/cjs/preview/parse/index.js +34 -0
  19. package/dist/cjs/preview/parse/parseFacadeOperationCalldata.js +115 -0
  20. package/dist/cjs/preview/parse/parseOperationCalldata.js +46 -0
  21. package/dist/cjs/preview/parse/parsePoolOperationCalldata.js +77 -0
  22. package/dist/cjs/{history/inner-operations.js → preview/parse/types-adapters.js} +2 -2
  23. package/dist/cjs/preview/parse/types-facades.js +16 -0
  24. package/dist/cjs/preview/parse/types-pools.js +16 -0
  25. package/dist/cjs/preview/parse/types.js +37 -0
  26. package/dist/cjs/preview/prerequisites/AllowancePrerequisite.js +78 -0
  27. package/dist/cjs/preview/prerequisites/BalancePrerequisite.js +77 -0
  28. package/dist/cjs/preview/prerequisites/Prerequisite.js +85 -0
  29. package/dist/cjs/preview/prerequisites/buildPrerequisites.js +187 -0
  30. package/dist/cjs/preview/prerequisites/index.js +34 -0
  31. package/dist/cjs/preview/prerequisites/prepareAction.js +48 -0
  32. package/dist/cjs/preview/prerequisites/runPrerequisites.js +71 -0
  33. package/dist/cjs/preview/prerequisites/types.js +16 -0
  34. package/dist/cjs/preview/simulate/constants.js +28 -0
  35. package/dist/cjs/preview/simulate/errors.js +98 -0
  36. package/dist/cjs/preview/simulate/extractERC20Transfers.js +47 -0
  37. package/dist/cjs/preview/simulate/holders.js +45 -0
  38. package/dist/cjs/preview/simulate/index.js +40 -0
  39. package/dist/cjs/preview/simulate/simulateFacadeOperation.js +30 -0
  40. package/dist/cjs/preview/simulate/simulateOperation.js +37 -0
  41. package/dist/cjs/preview/simulate/simulatePoolOpMulticall.js +155 -0
  42. package/dist/cjs/preview/simulate/simulatePoolOpV1.js +106 -0
  43. package/dist/cjs/preview/simulate/simulatePoolOperation.js +62 -0
  44. package/dist/cjs/preview/simulate/types.js +16 -0
  45. package/dist/cjs/{history → preview/trace}/errors.js +0 -26
  46. package/dist/cjs/preview/trace/extractAdapterCallTraces.js +58 -0
  47. package/dist/cjs/{history → preview/trace}/extractTransfers.js +9 -12
  48. package/dist/cjs/{history → preview/trace}/findFacadeCalls.js +3 -3
  49. package/dist/cjs/preview/trace/index.js +30 -0
  50. package/dist/cjs/preview/trace/types.js +16 -0
  51. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +154 -0
  52. package/dist/esm/common-utils/utils/index.js +1 -0
  53. package/dist/esm/common-utils/utils/trace.js +93 -0
  54. package/dist/esm/dev/index.js +1 -0
  55. package/dist/esm/dev/verifyTestnet.js +27 -0
  56. package/dist/esm/history/assembleOperations.js +8 -6
  57. package/dist/esm/history/classifyMulticallOperations.js +29 -23
  58. package/dist/esm/history/index.js +0 -1
  59. package/dist/esm/history/parseCreditAccountTransaction.js +3 -4
  60. package/dist/esm/history/toLegacyOperation.js +5 -1
  61. package/dist/esm/plugins/adapters/contracts/AbstractAdapter.js +28 -38
  62. package/dist/esm/plugins/adapters/contracts/AccountMigratorAdapterContract.js +9 -0
  63. package/dist/esm/preview/index.js +4 -0
  64. package/dist/esm/preview/package.json +1 -0
  65. package/dist/esm/preview/parse/classifyInnerOperations.js +68 -0
  66. package/dist/esm/preview/parse/errors.js +22 -0
  67. package/dist/esm/preview/parse/extractExpectedBalanceChanges.js +24 -0
  68. package/dist/esm/preview/parse/index.js +7 -0
  69. package/dist/esm/preview/parse/parseFacadeOperationCalldata.js +91 -0
  70. package/dist/esm/preview/parse/parseOperationCalldata.js +25 -0
  71. package/dist/esm/preview/parse/parsePoolOperationCalldata.js +53 -0
  72. package/dist/esm/preview/parse/types-facades.js +0 -0
  73. package/dist/esm/preview/parse/types-pools.js +0 -0
  74. package/dist/esm/preview/parse/types.js +9 -0
  75. package/dist/esm/preview/prerequisites/AllowancePrerequisite.js +57 -0
  76. package/dist/esm/preview/prerequisites/BalancePrerequisite.js +56 -0
  77. package/dist/esm/preview/prerequisites/Prerequisite.js +63 -0
  78. package/dist/esm/preview/prerequisites/buildPrerequisites.js +163 -0
  79. package/dist/esm/preview/prerequisites/index.js +7 -0
  80. package/dist/esm/preview/prerequisites/prepareAction.js +23 -0
  81. package/dist/esm/preview/prerequisites/runPrerequisites.js +47 -0
  82. package/dist/esm/preview/prerequisites/types.js +0 -0
  83. package/dist/esm/preview/simulate/constants.js +4 -0
  84. package/dist/esm/preview/simulate/errors.js +75 -0
  85. package/dist/esm/preview/simulate/extractERC20Transfers.js +23 -0
  86. package/dist/esm/preview/simulate/holders.js +21 -0
  87. package/dist/esm/preview/simulate/index.js +12 -0
  88. package/dist/esm/preview/simulate/simulateFacadeOperation.js +6 -0
  89. package/dist/esm/preview/simulate/simulateOperation.js +13 -0
  90. package/dist/esm/preview/simulate/simulatePoolOpMulticall.js +130 -0
  91. package/dist/esm/preview/simulate/simulatePoolOpV1.js +82 -0
  92. package/dist/esm/preview/simulate/simulatePoolOperation.js +41 -0
  93. package/dist/esm/preview/simulate/types.js +0 -0
  94. package/dist/esm/{history → preview/trace}/errors.js +0 -24
  95. package/dist/esm/preview/trace/extractAdapterCallTraces.js +40 -0
  96. package/dist/esm/{history → preview/trace}/extractTransfers.js +9 -12
  97. package/dist/esm/{history → preview/trace}/findFacadeCalls.js +4 -2
  98. package/dist/esm/preview/trace/index.js +5 -0
  99. package/dist/esm/preview/trace/types.js +0 -0
  100. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +154 -0
  101. package/dist/types/common-utils/utils/index.d.ts +1 -0
  102. package/dist/types/common-utils/utils/trace.d.ts +73 -0
  103. package/dist/types/dev/index.d.ts +1 -0
  104. package/dist/types/dev/verifyTestnet.d.ts +24 -0
  105. package/dist/types/history/assembleOperations.d.ts +11 -6
  106. package/dist/types/history/classifyMulticallOperations.d.ts +21 -9
  107. package/dist/types/history/index.d.ts +0 -1
  108. package/dist/types/history/mapOperations.d.ts +7 -9
  109. package/dist/types/history/types.d.ts +22 -71
  110. package/dist/types/plugins/adapters/contracts/AbstractAdapter.d.ts +16 -17
  111. package/dist/types/plugins/adapters/contracts/AccountMigratorAdapterContract.d.ts +10 -1
  112. package/dist/types/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.d.ts +1 -1
  113. package/dist/types/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.d.ts +1 -1
  114. package/dist/types/plugins/adapters/contracts/Curve2AssetsAdapterContract.d.ts +1 -1
  115. package/dist/types/plugins/adapters/contracts/Curve3AssetsAdapterContract.d.ts +1 -1
  116. package/dist/types/plugins/adapters/contracts/Curve4AssetsAdapterContract.d.ts +1 -1
  117. package/dist/types/plugins/adapters/contracts/CurveV1AdapterDeposit.d.ts +1 -1
  118. package/dist/types/plugins/adapters/contracts/CurveV1AdapterStETHContract.d.ts +1 -1
  119. package/dist/types/plugins/adapters/contracts/CurveV1StableNGAdapterContract.d.ts +1 -1
  120. package/dist/types/plugins/adapters/contracts/DaiUsdsAdapterContract.d.ts +1 -1
  121. package/dist/types/plugins/adapters/contracts/ERC4626AdapterContract.d.ts +1 -1
  122. package/dist/types/plugins/adapters/contracts/ERC4626ReferralAdapterContract.d.ts +1 -1
  123. package/dist/types/plugins/adapters/contracts/LidoV1AdapterContract.d.ts +1 -1
  124. package/dist/types/plugins/adapters/contracts/MellowDVVAdapterContract.d.ts +1 -1
  125. package/dist/types/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.d.ts +1 -1
  126. package/dist/types/plugins/adapters/contracts/UniswapV2AdapterContract.d.ts +1 -1
  127. package/dist/types/plugins/adapters/contracts/UniswapV4AdapterContract.d.ts +1 -1
  128. package/dist/types/plugins/adapters/contracts/WstETHV1AdapterContract.d.ts +1 -1
  129. package/dist/types/plugins/adapters/transferHelpers.d.ts +1 -1
  130. package/dist/types/plugins/adapters/transfers.d.ts +17 -0
  131. package/dist/types/plugins/adapters/types.d.ts +8 -46
  132. package/dist/types/preview/index.d.ts +4 -0
  133. package/dist/types/preview/parse/classifyInnerOperations.d.ts +21 -0
  134. package/dist/types/preview/parse/errors.d.ts +17 -0
  135. package/dist/types/preview/parse/extractExpectedBalanceChanges.d.ts +22 -0
  136. package/dist/types/preview/parse/index.d.ts +7 -0
  137. package/dist/types/preview/parse/parseFacadeOperationCalldata.d.ts +19 -0
  138. package/dist/types/preview/parse/parseOperationCalldata.d.ts +23 -0
  139. package/dist/types/preview/parse/parsePoolOperationCalldata.d.ts +17 -0
  140. package/dist/types/preview/parse/types-adapters.d.ts +69 -0
  141. package/dist/types/preview/parse/types-facades.d.ts +158 -0
  142. package/dist/types/preview/parse/types-pools.d.ts +55 -0
  143. package/dist/types/preview/parse/types.d.ts +44 -0
  144. package/dist/types/preview/prerequisites/AllowancePrerequisite.d.ts +24 -0
  145. package/dist/types/preview/prerequisites/BalancePrerequisite.d.ts +23 -0
  146. package/dist/types/preview/prerequisites/Prerequisite.d.ts +60 -0
  147. package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +16 -0
  148. package/dist/types/preview/prerequisites/index.d.ts +7 -0
  149. package/dist/types/preview/prerequisites/prepareAction.d.ts +52 -0
  150. package/dist/types/preview/prerequisites/runPrerequisites.d.ts +12 -0
  151. package/dist/types/preview/prerequisites/types.d.ts +78 -0
  152. package/dist/types/preview/simulate/constants.d.ts +6 -0
  153. package/dist/types/preview/simulate/errors.d.ts +51 -0
  154. package/dist/types/preview/simulate/extractERC20Transfers.d.ts +11 -0
  155. package/dist/types/preview/simulate/holders.d.ts +7 -0
  156. package/dist/types/preview/simulate/index.d.ts +9 -0
  157. package/dist/types/preview/simulate/simulateFacadeOperation.d.ts +25 -0
  158. package/dist/types/preview/simulate/simulateOperation.d.ts +20 -0
  159. package/dist/types/preview/simulate/simulatePoolOpMulticall.d.ts +28 -0
  160. package/dist/types/preview/simulate/simulatePoolOpV1.d.ts +14 -0
  161. package/dist/types/preview/simulate/simulatePoolOperation.d.ts +8 -0
  162. package/dist/types/preview/simulate/types.d.ts +79 -0
  163. package/dist/types/{history → preview/trace}/errors.d.ts +0 -10
  164. package/dist/types/preview/trace/extractAdapterCallTraces.d.ts +23 -0
  165. package/dist/types/{history → preview/trace}/extractTransfers.d.ts +14 -5
  166. package/dist/types/{history → preview/trace}/findFacadeCalls.d.ts +3 -2
  167. package/dist/types/preview/trace/index.d.ts +5 -0
  168. package/dist/types/preview/trace/types.d.ts +21 -0
  169. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +21 -1
  170. package/dist/types/sdk/accounts/types.d.ts +82 -0
  171. package/package.json +6 -1
  172. package/dist/cjs/history/extractProtocolCalls.js +0 -53
  173. package/dist/esm/history/extractProtocolCalls.js +0 -32
  174. package/dist/esm/history/trace-utils.js +0 -36
  175. package/dist/types/history/extractProtocolCalls.d.ts +0 -8
  176. package/dist/types/history/inner-operations.d.ts +0 -57
  177. package/dist/types/history/internal-types.d.ts +0 -47
  178. package/dist/types/history/trace-utils.d.ts +0 -12
  179. /package/dist/esm/{history/inner-operations.js → plugins/adapters/transfers.js} +0 -0
  180. /package/dist/esm/{history/internal-types.js → preview/parse/types-adapters.js} +0 -0
@@ -0,0 +1,47 @@
1
+ async function verifyPrerequisites(prereqs, ctx) {
2
+ if (prereqs.length === 0) {
3
+ return [];
4
+ }
5
+ const ranges = [];
6
+ const calls = [];
7
+ for (const prereq of prereqs) {
8
+ const start = calls.length;
9
+ calls.push(...prereq.calls(ctx));
10
+ ranges.push({ start, end: calls.length });
11
+ }
12
+ let results;
13
+ try {
14
+ results = await ctx.sdk.client.multicall({
15
+ allowFailure: true,
16
+ contracts: calls,
17
+ // `undefined` lets viem read at `latest`; `blockNumber` is only set for
18
+ // testnet forks pinned to a specific block.
19
+ blockNumber: ctx.blockNumber
20
+ });
21
+ } catch (cause) {
22
+ const error = cause instanceof Error ? cause : new Error(String(cause));
23
+ return prereqs.map(
24
+ (prereq, i) => (
25
+ // Each prereq pairs its own kind with its detail, so the widened
26
+ // `resolve` return is safe to narrow back to the discriminated union.
27
+ prereq.resolve(
28
+ failureSlice(ranges[i].end - ranges[i].start, error)
29
+ )
30
+ )
31
+ );
32
+ }
33
+ return prereqs.map(
34
+ (prereq, i) => prereq.resolve(
35
+ results.slice(ranges[i].start, ranges[i].end)
36
+ )
37
+ );
38
+ }
39
+ function failureSlice(n, error) {
40
+ return Array.from({ length: n }, () => ({
41
+ status: "failure",
42
+ error
43
+ }));
44
+ }
45
+ export {
46
+ verifyPrerequisites
47
+ };
File without changes
@@ -0,0 +1,4 @@
1
+ const ETH_SIMULATE_V1_NETWORKS = /* @__PURE__ */ new Set(["Mainnet", "Plasma", "Somnia"]);
2
+ export {
3
+ ETH_SIMULATE_V1_NETWORKS
4
+ };
@@ -0,0 +1,75 @@
1
+ import {
2
+ BaseError,
3
+ ContractFunctionRevertedError,
4
+ decodeErrorResult
5
+ } from "viem";
6
+ import { errorAbis } from "../../abi/errors.js";
7
+ class PreviewSimulationError extends BaseError {
8
+ name = "PreviewSimulationError";
9
+ /** Per-flow decoded failures behind this error. */
10
+ failures;
11
+ constructor(failures) {
12
+ const shortMessage = failures.length <= 1 ? failures[0]?.detail.reason ?? "simulation failed" : "all simulation flows failed";
13
+ const cause = failures.find((f) => f.detail.cause instanceof Error)?.detail.cause;
14
+ super(shortMessage, {
15
+ metaMessages: failures.map((f) => `[${f.source}] ${f.detail.reason}`),
16
+ cause
17
+ });
18
+ this.failures = failures;
19
+ }
20
+ }
21
+ function asPreviewSimulationError(reason, source) {
22
+ if (reason instanceof PreviewSimulationError) {
23
+ return reason;
24
+ }
25
+ const error = reason instanceof Error ? reason : new Error(String(reason));
26
+ return new PreviewSimulationError([
27
+ { source, detail: decodeSimulationError({ error }) }
28
+ ]);
29
+ }
30
+ function combinePreviewSimulationErrors(...errors) {
31
+ return new PreviewSimulationError(
32
+ errors.filter((e) => e).flatMap((e) => e?.failures ?? [])
33
+ );
34
+ }
35
+ function decodeSimulationError(revert) {
36
+ const { error, data } = revert;
37
+ if (data && data !== "0x") {
38
+ try {
39
+ const decoded = decodeErrorResult({ abi: errorAbis, data });
40
+ return {
41
+ reason: formatDecodedError(decoded.errorName, decoded.args),
42
+ cause: error
43
+ };
44
+ } catch {
45
+ }
46
+ }
47
+ if (error instanceof BaseError) {
48
+ const reverted = error.walk(
49
+ (e) => e instanceof ContractFunctionRevertedError
50
+ );
51
+ if (reverted instanceof ContractFunctionRevertedError) {
52
+ return {
53
+ reason: reverted.data?.errorName ?? reverted.reason ?? reverted.shortMessage ?? "reverted",
54
+ cause: error
55
+ };
56
+ }
57
+ return { reason: error.shortMessage ?? error.name, cause: error };
58
+ }
59
+ if (error instanceof Error) {
60
+ return { reason: error.message, cause: error };
61
+ }
62
+ return { reason: "reverted", cause: error };
63
+ }
64
+ function formatDecodedError(errorName, args) {
65
+ if (!args || args.length === 0) {
66
+ return errorName;
67
+ }
68
+ return `${errorName}(${args.map((arg) => String(arg)).join(", ")})`;
69
+ }
70
+ export {
71
+ PreviewSimulationError,
72
+ asPreviewSimulationError,
73
+ combinePreviewSimulationErrors,
74
+ decodeSimulationError
75
+ };
@@ -0,0 +1,23 @@
1
+ import { isAddressEqual, parseEventLogs } from "viem";
2
+ import { ierc20Abi } from "../../abi/iERC20.js";
3
+ function extractERC20Transfers(logs, watch) {
4
+ const parsed = parseEventLogs({
5
+ abi: ierc20Abi,
6
+ eventName: "Transfer",
7
+ logs
8
+ });
9
+ const transfers = [];
10
+ for (const log of parsed) {
11
+ const { from, to, value } = log.args;
12
+ const involved = watch.some(
13
+ (address) => isAddressEqual(from, address) || isAddressEqual(to, address)
14
+ );
15
+ if (involved) {
16
+ transfers.push({ token: log.address, amount: value, from, to });
17
+ }
18
+ }
19
+ return transfers;
20
+ }
21
+ export {
22
+ extractERC20Transfers
23
+ };
@@ -0,0 +1,21 @@
1
+ import { AddressSet } from "../../sdk/index.js";
2
+ function sourceHolder(operation, wallet) {
3
+ switch (operation.operation) {
4
+ case "Deposit":
5
+ case "Mint":
6
+ return wallet;
7
+ case "Withdraw":
8
+ case "Redeem":
9
+ return operation.owner;
10
+ }
11
+ }
12
+ function watchedHolders(operation, wallet) {
13
+ const holders = new AddressSet([
14
+ sourceHolder(operation, wallet),
15
+ operation.receiver
16
+ ]);
17
+ return holders.asArray();
18
+ }
19
+ export {
20
+ watchedHolders
21
+ };
@@ -0,0 +1,12 @@
1
+ import { ETH_SIMULATE_V1_NETWORKS } from "./constants.js";
2
+ import { PreviewSimulationError } from "./errors.js";
3
+ import { simulateFacadeOperation } from "./simulateFacadeOperation.js";
4
+ import { simulateOperation } from "./simulateOperation.js";
5
+ import { simulatePoolOperation } from "./simulatePoolOperation.js";
6
+ export {
7
+ ETH_SIMULATE_V1_NETWORKS,
8
+ PreviewSimulationError,
9
+ simulateFacadeOperation,
10
+ simulateOperation,
11
+ simulatePoolOperation
12
+ };
@@ -0,0 +1,6 @@
1
+ async function simulateFacadeOperation(_input, _options) {
2
+ throw new Error("not yet implemented");
3
+ }
4
+ export {
5
+ simulateFacadeOperation
6
+ };
@@ -0,0 +1,13 @@
1
+ import { isPoolOperation } from "../parse/index.js";
2
+ import { simulateFacadeOperation } from "./simulateFacadeOperation.js";
3
+ import { simulatePoolOperation } from "./simulatePoolOperation.js";
4
+ async function simulateOperation(input, options) {
5
+ const { operation } = input;
6
+ if (isPoolOperation(operation)) {
7
+ return simulatePoolOperation({ ...input, operation }, options);
8
+ }
9
+ return simulateFacadeOperation({ ...input, operation }, options);
10
+ }
11
+ export {
12
+ simulateOperation
13
+ };
@@ -0,0 +1,130 @@
1
+ import { iPoolV310Abi } from "../../abi/310/generated.js";
2
+ import { ierc20Abi } from "../../abi/iERC20.js";
3
+ import { AddressMap } from "../../sdk/index.js";
4
+ import { decodeSimulationError, PreviewSimulationError } from "./errors.js";
5
+ import { watchedHolders } from "./holders.js";
6
+ function previewRead(operation) {
7
+ switch (operation.operation) {
8
+ case "Deposit":
9
+ return { functionName: "previewDeposit", amount: operation.assets };
10
+ case "Mint":
11
+ return { functionName: "previewMint", amount: operation.shares };
12
+ case "Withdraw":
13
+ return { functionName: "previewWithdraw", amount: operation.assets };
14
+ case "Redeem":
15
+ return { functionName: "previewRedeem", amount: operation.shares };
16
+ }
17
+ }
18
+ async function simulatePoolOpMulticall(input, options = {}) {
19
+ const { sdk, operation, wallet } = input;
20
+ const { blockNumber } = options;
21
+ const { underlying, pool } = operation;
22
+ const holders = watchedHolders(operation, wallet);
23
+ const tokens = [underlying, pool];
24
+ const balanceCalls = holders.flatMap(
25
+ (holder) => tokens.map((token) => ({ holder, token }))
26
+ );
27
+ const balanceContracts = balanceCalls.map(
28
+ ({ holder, token }) => ({
29
+ address: token,
30
+ abi: ierc20Abi,
31
+ functionName: "balanceOf",
32
+ args: [holder]
33
+ })
34
+ );
35
+ const { functionName, amount } = previewRead(operation);
36
+ const previewContract = {
37
+ address: pool,
38
+ abi: iPoolV310Abi,
39
+ functionName,
40
+ args: [amount]
41
+ };
42
+ let results;
43
+ try {
44
+ results = await sdk.client.multicall({
45
+ allowFailure: false,
46
+ // `undefined` lets viem read at `latest`; `blockNumber` is only set for
47
+ // testnet forks pinned to a specific block.
48
+ blockNumber,
49
+ contracts: [...balanceContracts, previewContract]
50
+ });
51
+ } catch (cause) {
52
+ throw new PreviewSimulationError([
53
+ {
54
+ source: "multicall",
55
+ detail: decodeSimulationError({
56
+ error: cause instanceof Error ? cause : new Error(String(cause))
57
+ })
58
+ }
59
+ ]);
60
+ }
61
+ const previewAmount = results[balanceContracts.length];
62
+ const balances = new AddressMap();
63
+ for (const [i, { holder, token }] of balanceCalls.entries()) {
64
+ const tokenBalances = balances.get(holder) ?? new AddressMap();
65
+ tokenBalances.upsert(token, results[i]);
66
+ balances.upsert(holder, tokenBalances);
67
+ }
68
+ const before = (token, holder) => balances.get(holder)?.get(token) ?? 0n;
69
+ return {
70
+ balanceChanges: computePoolOpBalanceChanges(
71
+ operation,
72
+ wallet,
73
+ previewAmount,
74
+ before
75
+ ),
76
+ transfers: void 0
77
+ };
78
+ }
79
+ function balanceLegs(operation, wallet, previewAmount) {
80
+ const { underlying, pool, receiver } = operation;
81
+ switch (operation.operation) {
82
+ case "Deposit":
83
+ return [
84
+ { address: wallet, token: underlying, delta: -operation.assets },
85
+ { address: receiver, token: pool, delta: previewAmount }
86
+ ];
87
+ case "Mint":
88
+ return [
89
+ { address: wallet, token: underlying, delta: -previewAmount },
90
+ { address: receiver, token: pool, delta: operation.shares }
91
+ ];
92
+ case "Withdraw":
93
+ return [
94
+ { address: operation.owner, token: pool, delta: -previewAmount },
95
+ { address: receiver, token: underlying, delta: operation.assets }
96
+ ];
97
+ case "Redeem":
98
+ return [
99
+ { address: operation.owner, token: pool, delta: -operation.shares },
100
+ { address: receiver, token: underlying, delta: previewAmount }
101
+ ];
102
+ }
103
+ }
104
+ function computePoolOpBalanceChanges(operation, wallet, previewAmount, before) {
105
+ const byAddress = new AddressMap();
106
+ for (const { address, token, delta } of balanceLegs(
107
+ operation,
108
+ wallet,
109
+ previewAmount
110
+ )) {
111
+ const beforeBalance = before(token, address);
112
+ const change = {
113
+ token,
114
+ before: beforeBalance,
115
+ after: beforeBalance + delta,
116
+ delta
117
+ };
118
+ const existing = byAddress.get(address);
119
+ if (existing) {
120
+ existing.changes.push(change);
121
+ } else {
122
+ byAddress.upsert(address, { address, changes: [change] });
123
+ }
124
+ }
125
+ return byAddress.values();
126
+ }
127
+ export {
128
+ computePoolOpBalanceChanges,
129
+ simulatePoolOpMulticall
130
+ };
@@ -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
+ };
@@ -0,0 +1,41 @@
1
+ import { ETH_SIMULATE_V1_NETWORKS } from "./constants.js";
2
+ import {
3
+ asPreviewSimulationError,
4
+ combinePreviewSimulationErrors
5
+ } from "./errors.js";
6
+ import { simulatePoolOpMulticall } from "./simulatePoolOpMulticall.js";
7
+ import { simulatePoolOpV1 } from "./simulatePoolOpV1.js";
8
+ async function simulatePoolOperation(input, options = {}) {
9
+ const { sdk } = input;
10
+ const { logger } = options;
11
+ const useSimulateV1 = options.useSimulateV1 ?? ETH_SIMULATE_V1_NETWORKS.has(sdk.networkType);
12
+ logger?.debug(
13
+ { wallet: input.wallet, to: input.to },
14
+ "simulating pool operation"
15
+ );
16
+ const [v1, multicall] = await Promise.allSettled([
17
+ useSimulateV1 ? simulatePoolOpV1(input, options) : void 0,
18
+ simulatePoolOpMulticall(input, options)
19
+ ]);
20
+ if (v1.status === "fulfilled" && v1.value) {
21
+ return { status: "success", ...v1.value };
22
+ }
23
+ if (multicall.status === "fulfilled") {
24
+ if (v1.status === "rejected") {
25
+ logger?.debug(
26
+ asPreviewSimulationError(v1.reason, "eth_simulateV1"),
27
+ "eth_simulateV1 flow failed; falling back to multicall result"
28
+ );
29
+ }
30
+ return { status: "success", ...multicall.value };
31
+ }
32
+ const error = combinePreviewSimulationErrors(
33
+ v1.status === "rejected" ? asPreviewSimulationError(v1.reason, "eth_simulateV1") : void 0,
34
+ asPreviewSimulationError(multicall.reason, "multicall")
35
+ );
36
+ logger?.error(error, "pool operation simulation failed");
37
+ return { status: "failure", error };
38
+ }
39
+ export {
40
+ simulatePoolOperation
41
+ };
File without changes
@@ -22,28 +22,6 @@ class WithdrawCollateralAlignmentError extends Error {
22
22
  this.name = "WithdrawCollateralAlignmentError";
23
23
  }
24
24
  }
25
- class ProtocolCallNotFoundError extends Error {
26
- targetContract;
27
- executeIndex;
28
- constructor(targetContract, executeIndex) {
29
- super(
30
- `protocol call to ${targetContract} not found in trace for Execute #${executeIndex}`
31
- );
32
- this.name = "ProtocolCallNotFoundError";
33
- this.targetContract = targetContract;
34
- this.executeIndex = executeIndex;
35
- }
36
- }
37
- class AdapterTraceAlignmentError extends Error {
38
- constructor(expected, actual) {
39
- super(`found ${actual} adapter traces for ${expected} execute events`);
40
- this.expected = expected;
41
- this.actual = actual;
42
- this.name = "AdapterTracesAlignmentError";
43
- }
44
- expected;
45
- actual;
46
- }
47
25
  class UnexpectedFacadeEventOrderError extends Error {
48
26
  constructor(e) {
49
27
  super(
@@ -63,8 +41,6 @@ class UnknownFacadeCallError extends Error {
63
41
  }
64
42
  }
65
43
  export {
66
- AdapterTraceAlignmentError,
67
- ProtocolCallNotFoundError,
68
44
  TransferAlignmentError,
69
45
  UnexpectedFacadeEventOrderError,
70
46
  UnknownAdapterError,
@@ -0,0 +1,40 @@
1
+ import {
2
+ decodeAbiParameters,
3
+ isAddressEqual,
4
+ toFunctionSelector
5
+ } from "viem";
6
+ import {
7
+ resolveProtocolCall
8
+ } from "../../common-utils/utils/trace.js";
9
+ const WITHDRAW_PHANTOM_TOKEN_SELECTOR = toFunctionSelector(
10
+ "withdrawPhantomToken(address,uint256)"
11
+ );
12
+ const GET_PHANTOM_TOKEN_INFO_SELECTOR = toFunctionSelector(
13
+ "getPhantomTokenInfo()"
14
+ );
15
+ function isSynthesizedPhantomWithdrawal(siblings, index) {
16
+ const node = siblings[index];
17
+ if (node.type !== "CALL" || node.input.slice(0, 10).toLowerCase() !== WITHDRAW_PHANTOM_TOKEN_SELECTOR) {
18
+ return false;
19
+ }
20
+ const [token] = decodeAbiParameters(
21
+ [{ type: "address" }, { type: "uint256" }],
22
+ `0x${node.input.slice(10)}`
23
+ );
24
+ for (let i = 0; i < index; i++) {
25
+ const sib = siblings[i];
26
+ if (sib.type === "STATICCALL" && sib.input.slice(0, 10).toLowerCase() === GET_PHANTOM_TOKEN_INFO_SELECTOR && isAddressEqual(sib.to, token)) {
27
+ return true;
28
+ }
29
+ }
30
+ return false;
31
+ }
32
+ function extractAdapterCallTraces(facadeTrace) {
33
+ const subtraces = facadeTrace.calls ?? [];
34
+ return subtraces.filter(
35
+ (sub, index) => resolveProtocolCall(sub) !== void 0 && !isSynthesizedPhantomWithdrawal(subtraces, index)
36
+ );
37
+ }
38
+ export {
39
+ extractAdapterCallTraces
40
+ };
@@ -3,9 +3,9 @@ import {
3
3
  isAddressEqual,
4
4
  parseEventLogs
5
5
  } from "viem";
6
- import { iCreditFacadeV310Abi } from "../abi/310/generated.js";
7
- import { ierc20Abi } from "../abi/iERC20.js";
8
- import { AddressMap } from "../sdk/index.js";
6
+ import { iCreditFacadeV310Abi } from "../../abi/310/generated.js";
7
+ import { ierc20Abi } from "../../abi/iERC20.js";
8
+ import { AddressMap } from "../../sdk/index.js";
9
9
  import { UnexpectedFacadeEventOrderError } from "./errors.js";
10
10
  function extractTransfers(logs, creditAccount, pool, creditFacade) {
11
11
  const ranges = buildOperationRanges(logs, creditFacade, creditAccount);
@@ -14,7 +14,7 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
14
14
  return !!e && (e.eventName === "LiquidateCreditAccount" || e.eventName === "PartiallyLiquidateCreditAccount") && isAddressEqual(e.args.creditAccount, creditAccount);
15
15
  });
16
16
  let currentEntries = [];
17
- const executeResults = [];
17
+ const executeTransfers = [];
18
18
  const directTransfers = [];
19
19
  const phantomTokens = new AddressMap();
20
20
  const withdrawCollateralEvents = [];
@@ -23,20 +23,17 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
23
23
  const facadeEvent = tryDecodeFacadeEvent(log, creditFacade);
24
24
  if (facadeEvent) {
25
25
  if (isExecute(facadeEvent, creditAccount)) {
26
- executeResults.push({
27
- transfers: currentEntries,
28
- targetContract: facadeEvent.args.targetContract
29
- });
26
+ executeTransfers.push(currentEntries);
30
27
  } else if (isLiquidation(facadeEvent, creditAccount)) {
31
28
  liquidationRemainingFunds = facadeEvent.args.remainingFunds;
32
29
  } else if (isWithdrawPhantomToken(facadeEvent, creditAccount)) {
33
- const phantomExec = executeResults.pop();
34
- if (!phantomExec) {
30
+ const phantomTransfers = executeTransfers.pop();
31
+ if (!phantomTransfers) {
35
32
  throw new Error(
36
33
  `WithdrawPhantomToken without preceding Execute at logIndex ${facadeEvent.logIndex}`
37
34
  );
38
35
  }
39
- const rawDeposit = phantomExec.transfers.find(
36
+ const rawDeposit = phantomTransfers.find(
40
37
  (t) => isAddressEqual(t.to, creditAccount)
41
38
  );
42
39
  if (!rawDeposit) {
@@ -80,7 +77,7 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
80
77
  }
81
78
  }
82
79
  return {
83
- executeResults,
80
+ executeTransfers,
84
81
  directTransfers,
85
82
  liquidationRemainingFunds,
86
83
  phantomTokens,
@@ -2,9 +2,11 @@ import {
2
2
  decodeFunctionResult,
3
3
  isAddressEqual
4
4
  } from "viem";
5
- import { iCreditFacadeV310Abi } from "../abi/310/generated.js";
5
+ import { iCreditFacadeV310Abi } from "../../abi/310/generated.js";
6
+ import {
7
+ collectTraces
8
+ } from "../../common-utils/utils/trace.js";
6
9
  import { UnknownFacadeCallError } from "./errors.js";
7
- import { collectTraces } from "./trace-utils.js";
8
10
  const FACADE_CALL_TYPES = {
9
11
  multicall: "MultiCall",
10
12
  botMulticall: "BotMulticall",
@@ -0,0 +1,5 @@
1
+ export * from "./errors.js";
2
+ export * from "./extractAdapterCallTraces.js";
3
+ export * from "./extractTransfers.js";
4
+ export * from "./findFacadeCalls.js";
5
+ export * from "./types.js";
File without changes