@gearbox-protocol/sdk 14.11.0-next.1 → 14.11.0-next.10

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 (165) 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 +124 -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 +3 -1
  14. package/dist/cjs/preview/parse/classifyInnerOperations.js +5 -43
  15. package/dist/cjs/preview/parse/extractExpectedBalanceChanges.js +48 -0
  16. package/dist/cjs/preview/parse/index.js +8 -6
  17. package/dist/cjs/preview/parse/{parseCreditFacadeOperation.js → parseFacadeOperationCalldata.js} +19 -15
  18. package/dist/cjs/preview/parse/{parseTransaction.js → parseOperationCalldata.js} +10 -10
  19. package/dist/cjs/preview/parse/{parsePoolOperation.js → parsePoolOperationCalldata.js} +27 -12
  20. package/dist/cjs/{history/inner-operations.js → preview/parse/types-adapters.js} +2 -2
  21. package/dist/cjs/preview/parse/types-facades.js +16 -0
  22. package/dist/cjs/preview/parse/types-pools.js +16 -0
  23. package/dist/cjs/preview/parse/types.js +9 -2
  24. package/dist/cjs/preview/prerequisites/buildPrerequisites.js +46 -0
  25. package/dist/cjs/preview/prerequisites/index.js +2 -0
  26. package/dist/cjs/preview/prerequisites/prepareAction.js +48 -0
  27. package/dist/cjs/preview/simulate/constants.js +28 -0
  28. package/dist/cjs/preview/simulate/{decodeSimulationError.js → errors.js} +37 -3
  29. package/dist/cjs/preview/simulate/holders.js +45 -0
  30. package/dist/cjs/preview/simulate/index.js +21 -9
  31. package/dist/cjs/preview/simulate/simulateFacadeOperation.js +30 -0
  32. package/dist/cjs/preview/simulate/simulateOperation.js +37 -0
  33. package/dist/cjs/preview/simulate/simulatePoolOpMulticall.js +155 -0
  34. package/dist/cjs/preview/simulate/simulatePoolOpV1.js +106 -0
  35. package/dist/cjs/preview/simulate/simulatePoolOperation.js +30 -62
  36. package/dist/cjs/{history → preview/trace}/errors.js +0 -26
  37. package/dist/cjs/preview/trace/extractAdapterCallTraces.js +58 -0
  38. package/dist/cjs/{history → preview/trace}/extractTransfers.js +10 -13
  39. package/dist/cjs/{history → preview/trace}/findFacadeCalls.js +3 -3
  40. package/dist/cjs/preview/trace/index.js +30 -0
  41. package/dist/cjs/preview/trace/types.js +16 -0
  42. package/dist/cjs/rewards/rewards/api.js +4 -2
  43. package/dist/cjs/rewards/rewards/merkl-api.js +9 -3
  44. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +154 -0
  45. package/dist/esm/common-utils/utils/index.js +1 -0
  46. package/dist/esm/common-utils/utils/trace.js +93 -0
  47. package/dist/esm/dev/index.js +1 -0
  48. package/dist/esm/dev/verifyTestnet.js +98 -0
  49. package/dist/esm/history/assembleOperations.js +8 -6
  50. package/dist/esm/history/classifyMulticallOperations.js +29 -23
  51. package/dist/esm/history/index.js +0 -1
  52. package/dist/esm/history/parseCreditAccountTransaction.js +3 -4
  53. package/dist/esm/history/toLegacyOperation.js +5 -1
  54. package/dist/esm/plugins/adapters/contracts/AbstractAdapter.js +28 -38
  55. package/dist/esm/plugins/adapters/contracts/AccountMigratorAdapterContract.js +9 -0
  56. package/dist/esm/preview/index.js +1 -0
  57. package/dist/esm/preview/parse/classifyInnerOperations.js +6 -46
  58. package/dist/esm/preview/parse/extractExpectedBalanceChanges.js +24 -0
  59. package/dist/esm/preview/parse/index.js +4 -3
  60. package/dist/esm/preview/parse/{parseCreditFacadeOperation.js → parseFacadeOperationCalldata.js} +16 -16
  61. package/dist/esm/preview/parse/{parseTransaction.js → parseOperationCalldata.js} +6 -6
  62. package/dist/esm/preview/parse/{parsePoolOperation.js → parsePoolOperationCalldata.js} +23 -8
  63. package/dist/esm/preview/parse/types-facades.js +0 -0
  64. package/dist/esm/preview/parse/types-pools.js +0 -0
  65. package/dist/esm/preview/parse/types.js +4 -1
  66. package/dist/esm/preview/prerequisites/buildPrerequisites.js +46 -0
  67. package/dist/esm/preview/prerequisites/index.js +1 -0
  68. package/dist/esm/preview/prerequisites/prepareAction.js +23 -0
  69. package/dist/esm/preview/simulate/constants.js +4 -0
  70. package/dist/esm/preview/simulate/{decodeSimulationError.js → errors.js} +31 -0
  71. package/dist/esm/preview/simulate/holders.js +21 -0
  72. package/dist/esm/preview/simulate/index.js +12 -4
  73. package/dist/esm/preview/simulate/simulateFacadeOperation.js +6 -0
  74. package/dist/esm/preview/simulate/simulateOperation.js +13 -0
  75. package/dist/esm/preview/simulate/simulatePoolOpMulticall.js +130 -0
  76. package/dist/esm/preview/simulate/simulatePoolOpV1.js +82 -0
  77. package/dist/esm/preview/simulate/simulatePoolOperation.js +33 -62
  78. package/dist/esm/{history → preview/trace}/errors.js +0 -24
  79. package/dist/esm/preview/trace/extractAdapterCallTraces.js +40 -0
  80. package/dist/esm/{history → preview/trace}/extractTransfers.js +10 -13
  81. package/dist/esm/{history → preview/trace}/findFacadeCalls.js +4 -2
  82. package/dist/esm/preview/trace/index.js +5 -0
  83. package/dist/esm/preview/trace/types.js +0 -0
  84. package/dist/esm/rewards/rewards/api.js +4 -2
  85. package/dist/esm/rewards/rewards/merkl-api.js +9 -3
  86. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +154 -0
  87. package/dist/types/common-utils/utils/index.d.ts +1 -0
  88. package/dist/types/common-utils/utils/trace.d.ts +73 -0
  89. package/dist/types/dev/index.d.ts +1 -0
  90. package/dist/types/dev/verifyTestnet.d.ts +82 -0
  91. package/dist/types/history/assembleOperations.d.ts +11 -6
  92. package/dist/types/history/classifyMulticallOperations.d.ts +21 -9
  93. package/dist/types/history/index.d.ts +0 -1
  94. package/dist/types/history/mapOperations.d.ts +7 -9
  95. package/dist/types/history/types.d.ts +22 -65
  96. package/dist/types/plugins/adapters/contracts/AbstractAdapter.d.ts +16 -17
  97. package/dist/types/plugins/adapters/contracts/AccountMigratorAdapterContract.d.ts +10 -1
  98. package/dist/types/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.d.ts +1 -1
  99. package/dist/types/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.d.ts +1 -1
  100. package/dist/types/plugins/adapters/contracts/Curve2AssetsAdapterContract.d.ts +1 -1
  101. package/dist/types/plugins/adapters/contracts/Curve3AssetsAdapterContract.d.ts +1 -1
  102. package/dist/types/plugins/adapters/contracts/Curve4AssetsAdapterContract.d.ts +1 -1
  103. package/dist/types/plugins/adapters/contracts/CurveV1AdapterDeposit.d.ts +1 -1
  104. package/dist/types/plugins/adapters/contracts/CurveV1AdapterStETHContract.d.ts +1 -1
  105. package/dist/types/plugins/adapters/contracts/CurveV1StableNGAdapterContract.d.ts +1 -1
  106. package/dist/types/plugins/adapters/contracts/DaiUsdsAdapterContract.d.ts +1 -1
  107. package/dist/types/plugins/adapters/contracts/ERC4626AdapterContract.d.ts +1 -1
  108. package/dist/types/plugins/adapters/contracts/ERC4626ReferralAdapterContract.d.ts +1 -1
  109. package/dist/types/plugins/adapters/contracts/LidoV1AdapterContract.d.ts +1 -1
  110. package/dist/types/plugins/adapters/contracts/MellowDVVAdapterContract.d.ts +1 -1
  111. package/dist/types/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.d.ts +1 -1
  112. package/dist/types/plugins/adapters/contracts/UniswapV2AdapterContract.d.ts +1 -1
  113. package/dist/types/plugins/adapters/contracts/UniswapV4AdapterContract.d.ts +1 -1
  114. package/dist/types/plugins/adapters/contracts/WstETHV1AdapterContract.d.ts +1 -1
  115. package/dist/types/plugins/adapters/transferHelpers.d.ts +1 -1
  116. package/dist/types/plugins/adapters/transfers.d.ts +17 -0
  117. package/dist/types/plugins/adapters/types.d.ts +8 -46
  118. package/dist/types/preview/index.d.ts +1 -0
  119. package/dist/types/preview/parse/classifyInnerOperations.d.ts +8 -8
  120. package/dist/types/preview/parse/extractExpectedBalanceChanges.d.ts +22 -0
  121. package/dist/types/preview/parse/index.d.ts +4 -3
  122. package/dist/types/preview/parse/parseFacadeOperationCalldata.d.ts +19 -0
  123. package/dist/types/preview/parse/{parseTransaction.d.ts → parseOperationCalldata.d.ts} +4 -4
  124. package/dist/types/preview/parse/parsePoolOperationCalldata.d.ts +17 -0
  125. package/dist/types/preview/parse/types-adapters.d.ts +69 -0
  126. package/dist/types/preview/parse/types-facades.d.ts +157 -0
  127. package/dist/types/preview/parse/types-pools.d.ts +55 -0
  128. package/dist/types/preview/parse/types.d.ts +16 -50
  129. package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +3 -3
  130. package/dist/types/preview/prerequisites/index.d.ts +1 -0
  131. package/dist/types/preview/prerequisites/prepareAction.d.ts +52 -0
  132. package/dist/types/preview/simulate/constants.d.ts +6 -0
  133. package/dist/types/preview/simulate/errors.d.ts +51 -0
  134. package/dist/types/preview/simulate/extractERC20Transfers.d.ts +1 -1
  135. package/dist/types/preview/simulate/holders.d.ts +7 -0
  136. package/dist/types/preview/simulate/index.d.ts +9 -4
  137. package/dist/types/preview/simulate/simulateFacadeOperation.d.ts +25 -0
  138. package/dist/types/preview/simulate/simulateOperation.d.ts +20 -0
  139. package/dist/types/preview/simulate/simulatePoolOpMulticall.d.ts +28 -0
  140. package/dist/types/preview/simulate/simulatePoolOpV1.d.ts +14 -0
  141. package/dist/types/preview/simulate/simulatePoolOperation.d.ts +5 -27
  142. package/dist/types/preview/simulate/types.d.ts +54 -18
  143. package/dist/types/{history → preview/trace}/errors.d.ts +0 -10
  144. package/dist/types/preview/trace/extractAdapterCallTraces.d.ts +23 -0
  145. package/dist/types/{history → preview/trace}/extractTransfers.d.ts +14 -5
  146. package/dist/types/{history → preview/trace}/findFacadeCalls.d.ts +3 -2
  147. package/dist/types/preview/trace/index.d.ts +5 -0
  148. package/dist/types/preview/trace/types.d.ts +21 -0
  149. package/dist/types/rewards/rewards/api.d.ts +2 -1
  150. package/dist/types/rewards/rewards/merkl-api.d.ts +2 -1
  151. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +21 -1
  152. package/dist/types/sdk/accounts/types.d.ts +82 -0
  153. package/package.json +1 -1
  154. package/dist/cjs/history/extractProtocolCalls.js +0 -53
  155. package/dist/esm/history/extractProtocolCalls.js +0 -32
  156. package/dist/esm/history/trace-utils.js +0 -36
  157. package/dist/types/history/extractProtocolCalls.d.ts +0 -8
  158. package/dist/types/history/inner-operations.d.ts +0 -57
  159. package/dist/types/history/internal-types.d.ts +0 -47
  160. package/dist/types/history/trace-utils.d.ts +0 -12
  161. package/dist/types/preview/parse/parseCreditFacadeOperation.d.ts +0 -18
  162. package/dist/types/preview/parse/parsePoolOperation.d.ts +0 -15
  163. package/dist/types/preview/simulate/decodeSimulationError.d.ts +0 -18
  164. /package/dist/esm/{history/inner-operations.js → plugins/adapters/transfers.js} +0 -0
  165. /package/dist/esm/{history/internal-types.js → preview/parse/types-adapters.js} +0 -0
@@ -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
+ };
@@ -1,69 +1,40 @@
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 { 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"
20
15
  );
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
- };
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 };
40
22
  }
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 });
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
+ );
56
29
  }
30
+ return { status: "success", ...multicall.value };
57
31
  }
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;
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 };
67
38
  }
68
39
  export {
69
40
  simulatePoolOperation
@@ -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,14 +3,14 @@ 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);
12
12
  let currentEntries = [];
13
- const executeResults = [];
13
+ const executeTransfers = [];
14
14
  const directTransfers = [];
15
15
  const phantomTokens = new AddressMap();
16
16
  const withdrawCollateralEvents = [];
@@ -19,20 +19,17 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
19
19
  const facadeEvent = tryDecodeFacadeEvent(log, creditFacade);
20
20
  if (facadeEvent) {
21
21
  if (isExecute(facadeEvent, creditAccount)) {
22
- executeResults.push({
23
- transfers: currentEntries,
24
- targetContract: facadeEvent.args.targetContract
25
- });
22
+ executeTransfers.push(currentEntries);
26
23
  } else if (isLiquidation(facadeEvent, creditAccount)) {
27
24
  liquidationRemainingFunds = facadeEvent.args.remainingFunds;
28
25
  } else if (isWithdrawPhantomToken(facadeEvent, creditAccount)) {
29
- const phantomExec = executeResults.pop();
30
- if (!phantomExec) {
26
+ const phantomTransfers = executeTransfers.pop();
27
+ if (!phantomTransfers) {
31
28
  throw new Error(
32
29
  `WithdrawPhantomToken without preceding Execute at logIndex ${facadeEvent.logIndex}`
33
30
  );
34
31
  }
35
- const rawDeposit = phantomExec.transfers.find(
32
+ const rawDeposit = phantomTransfers.find(
36
33
  (t) => isAddressEqual(t.to, creditAccount)
37
34
  );
38
35
  if (!rawDeposit) {
@@ -67,11 +64,11 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
67
64
  currentEntries.push({ token, amount: value, from, to });
68
65
  }
69
66
  if (isAddressEqual(to, creditAccount) && !isInRange(log.logIndex, ranges)) {
70
- directTransfers.push({ token, from, amount: value });
67
+ directTransfers.push({ token, amount: value, from, to });
71
68
  }
72
69
  }
73
70
  return {
74
- executeResults,
71
+ executeTransfers,
75
72
  directTransfers,
76
73
  liquidationRemainingFunds,
77
74
  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
@@ -11,7 +11,8 @@ class RewardAmountAPI {
11
11
  pools,
12
12
  account,
13
13
  network,
14
- reportError
14
+ reportError,
15
+ apiKey
15
16
  }) {
16
17
  const [merkleXYZLMResponse] = await Promise.allSettled([
17
18
  MerkleXYZApi.fetchWithFallback(
@@ -20,7 +21,8 @@ class RewardAmountAPI {
20
21
  chainId: chains[network].id,
21
22
  user: getAddress(account)
22
23
  }
23
- })
24
+ }),
25
+ apiKey
24
26
  )
25
27
  ]);
26
28
  const merkleXYZLm = RewardAmountAPI.extractFulfilled(
@@ -4,11 +4,17 @@ class MerkleXYZApi {
4
4
  }
5
5
  static defaultDomain = "https://api.merkl.xyz";
6
6
  static angleDomain = "https://api-merkl.angle.money";
7
- static fetchWithFallback = async (getUrl) => {
7
+ static apiKeyHeader = "X-API-Key";
8
+ static fetchWithFallback = async (getUrl, apiKey) => {
9
+ const headers = apiKey ? { [MerkleXYZApi.apiKeyHeader]: apiKey } : void 0;
8
10
  try {
9
- return await axios.get(getUrl(MerkleXYZApi.defaultDomain));
11
+ return await axios.get(getUrl(MerkleXYZApi.defaultDomain), {
12
+ headers
13
+ });
10
14
  } catch {
11
- return await axios.get(getUrl(MerkleXYZApi.angleDomain));
15
+ return await axios.get(getUrl(MerkleXYZApi.angleDomain), {
16
+ headers
17
+ });
12
18
  }
13
19
  };
14
20
  static getUserRewardsUrl = (options) => (domain) => `${domain}/v4/users/${options.params.user}/rewards?chainId=${options.params.chainId}`;