@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.
- package/dist/cjs/common-utils/utils/index.js +2 -0
- package/dist/cjs/{history/trace-utils.js → common-utils/utils/trace.js} +62 -5
- package/dist/cjs/dev/index.js +3 -1
- package/dist/cjs/dev/verifyTestnet.js +124 -0
- package/dist/cjs/history/assembleOperations.js +6 -6
- package/dist/cjs/history/classifyMulticallOperations.js +31 -25
- package/dist/cjs/history/index.js +0 -2
- package/dist/cjs/history/parseCreditAccountTransaction.js +5 -6
- package/dist/cjs/history/toLegacyOperation.js +5 -1
- package/dist/cjs/plugins/adapters/contracts/AbstractAdapter.js +25 -37
- package/dist/cjs/plugins/adapters/contracts/AccountMigratorAdapterContract.js +9 -0
- package/dist/cjs/{history/internal-types.js → plugins/adapters/transfers.js} +2 -2
- package/dist/cjs/preview/index.js +3 -1
- package/dist/cjs/preview/parse/classifyInnerOperations.js +5 -43
- package/dist/cjs/preview/parse/extractExpectedBalanceChanges.js +48 -0
- package/dist/cjs/preview/parse/index.js +8 -6
- package/dist/cjs/preview/parse/{parseCreditFacadeOperation.js → parseFacadeOperationCalldata.js} +19 -15
- package/dist/cjs/preview/parse/{parseTransaction.js → parseOperationCalldata.js} +10 -10
- package/dist/cjs/preview/parse/{parsePoolOperation.js → parsePoolOperationCalldata.js} +27 -12
- package/dist/cjs/{history/inner-operations.js → preview/parse/types-adapters.js} +2 -2
- package/dist/cjs/preview/parse/types-facades.js +16 -0
- package/dist/cjs/preview/parse/types-pools.js +16 -0
- package/dist/cjs/preview/parse/types.js +9 -2
- package/dist/cjs/preview/prerequisites/buildPrerequisites.js +46 -0
- package/dist/cjs/preview/prerequisites/index.js +2 -0
- package/dist/cjs/preview/prerequisites/prepareAction.js +48 -0
- package/dist/cjs/preview/simulate/constants.js +28 -0
- package/dist/cjs/preview/simulate/{decodeSimulationError.js → errors.js} +37 -3
- package/dist/cjs/preview/simulate/holders.js +45 -0
- package/dist/cjs/preview/simulate/index.js +21 -9
- package/dist/cjs/preview/simulate/simulateFacadeOperation.js +30 -0
- package/dist/cjs/preview/simulate/simulateOperation.js +37 -0
- package/dist/cjs/preview/simulate/simulatePoolOpMulticall.js +155 -0
- package/dist/cjs/preview/simulate/simulatePoolOpV1.js +106 -0
- package/dist/cjs/preview/simulate/simulatePoolOperation.js +30 -62
- package/dist/cjs/{history → preview/trace}/errors.js +0 -26
- package/dist/cjs/preview/trace/extractAdapterCallTraces.js +58 -0
- package/dist/cjs/{history → preview/trace}/extractTransfers.js +10 -13
- package/dist/cjs/{history → preview/trace}/findFacadeCalls.js +3 -3
- package/dist/cjs/preview/trace/index.js +30 -0
- package/dist/cjs/preview/trace/types.js +16 -0
- package/dist/cjs/rewards/rewards/api.js +4 -2
- package/dist/cjs/rewards/rewards/merkl-api.js +9 -3
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +154 -0
- package/dist/esm/common-utils/utils/index.js +1 -0
- package/dist/esm/common-utils/utils/trace.js +93 -0
- package/dist/esm/dev/index.js +1 -0
- package/dist/esm/dev/verifyTestnet.js +98 -0
- package/dist/esm/history/assembleOperations.js +8 -6
- package/dist/esm/history/classifyMulticallOperations.js +29 -23
- package/dist/esm/history/index.js +0 -1
- package/dist/esm/history/parseCreditAccountTransaction.js +3 -4
- package/dist/esm/history/toLegacyOperation.js +5 -1
- package/dist/esm/plugins/adapters/contracts/AbstractAdapter.js +28 -38
- package/dist/esm/plugins/adapters/contracts/AccountMigratorAdapterContract.js +9 -0
- package/dist/esm/preview/index.js +1 -0
- package/dist/esm/preview/parse/classifyInnerOperations.js +6 -46
- package/dist/esm/preview/parse/extractExpectedBalanceChanges.js +24 -0
- package/dist/esm/preview/parse/index.js +4 -3
- package/dist/esm/preview/parse/{parseCreditFacadeOperation.js → parseFacadeOperationCalldata.js} +16 -16
- package/dist/esm/preview/parse/{parseTransaction.js → parseOperationCalldata.js} +6 -6
- package/dist/esm/preview/parse/{parsePoolOperation.js → parsePoolOperationCalldata.js} +23 -8
- package/dist/esm/preview/parse/types-facades.js +0 -0
- package/dist/esm/preview/parse/types-pools.js +0 -0
- package/dist/esm/preview/parse/types.js +4 -1
- package/dist/esm/preview/prerequisites/buildPrerequisites.js +46 -0
- package/dist/esm/preview/prerequisites/index.js +1 -0
- package/dist/esm/preview/prerequisites/prepareAction.js +23 -0
- package/dist/esm/preview/simulate/constants.js +4 -0
- package/dist/esm/preview/simulate/{decodeSimulationError.js → errors.js} +31 -0
- package/dist/esm/preview/simulate/holders.js +21 -0
- package/dist/esm/preview/simulate/index.js +12 -4
- package/dist/esm/preview/simulate/simulateFacadeOperation.js +6 -0
- package/dist/esm/preview/simulate/simulateOperation.js +13 -0
- package/dist/esm/preview/simulate/simulatePoolOpMulticall.js +130 -0
- package/dist/esm/preview/simulate/simulatePoolOpV1.js +82 -0
- package/dist/esm/preview/simulate/simulatePoolOperation.js +33 -62
- package/dist/esm/{history → preview/trace}/errors.js +0 -24
- package/dist/esm/preview/trace/extractAdapterCallTraces.js +40 -0
- package/dist/esm/{history → preview/trace}/extractTransfers.js +10 -13
- package/dist/esm/{history → preview/trace}/findFacadeCalls.js +4 -2
- package/dist/esm/preview/trace/index.js +5 -0
- package/dist/esm/preview/trace/types.js +0 -0
- package/dist/esm/rewards/rewards/api.js +4 -2
- package/dist/esm/rewards/rewards/merkl-api.js +9 -3
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +154 -0
- package/dist/types/common-utils/utils/index.d.ts +1 -0
- package/dist/types/common-utils/utils/trace.d.ts +73 -0
- package/dist/types/dev/index.d.ts +1 -0
- package/dist/types/dev/verifyTestnet.d.ts +82 -0
- package/dist/types/history/assembleOperations.d.ts +11 -6
- package/dist/types/history/classifyMulticallOperations.d.ts +21 -9
- package/dist/types/history/index.d.ts +0 -1
- package/dist/types/history/mapOperations.d.ts +7 -9
- package/dist/types/history/types.d.ts +22 -65
- package/dist/types/plugins/adapters/contracts/AbstractAdapter.d.ts +16 -17
- package/dist/types/plugins/adapters/contracts/AccountMigratorAdapterContract.d.ts +10 -1
- package/dist/types/plugins/adapters/contracts/ConvexV1BaseRewardPoolAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/ConvexV1BoosterAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/Curve2AssetsAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/Curve3AssetsAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/Curve4AssetsAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/CurveV1AdapterDeposit.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/CurveV1AdapterStETHContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/CurveV1StableNGAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/DaiUsdsAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/ERC4626AdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/ERC4626ReferralAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/LidoV1AdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/MellowDVVAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/MellowERC4626VaultAdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/UniswapV2AdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/UniswapV4AdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/contracts/WstETHV1AdapterContract.d.ts +1 -1
- package/dist/types/plugins/adapters/transferHelpers.d.ts +1 -1
- package/dist/types/plugins/adapters/transfers.d.ts +17 -0
- package/dist/types/plugins/adapters/types.d.ts +8 -46
- package/dist/types/preview/index.d.ts +1 -0
- package/dist/types/preview/parse/classifyInnerOperations.d.ts +8 -8
- package/dist/types/preview/parse/extractExpectedBalanceChanges.d.ts +22 -0
- package/dist/types/preview/parse/index.d.ts +4 -3
- package/dist/types/preview/parse/parseFacadeOperationCalldata.d.ts +19 -0
- package/dist/types/preview/parse/{parseTransaction.d.ts → parseOperationCalldata.d.ts} +4 -4
- package/dist/types/preview/parse/parsePoolOperationCalldata.d.ts +17 -0
- package/dist/types/preview/parse/types-adapters.d.ts +69 -0
- package/dist/types/preview/parse/types-facades.d.ts +157 -0
- package/dist/types/preview/parse/types-pools.d.ts +55 -0
- package/dist/types/preview/parse/types.d.ts +16 -50
- package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +3 -3
- package/dist/types/preview/prerequisites/index.d.ts +1 -0
- package/dist/types/preview/prerequisites/prepareAction.d.ts +52 -0
- package/dist/types/preview/simulate/constants.d.ts +6 -0
- package/dist/types/preview/simulate/errors.d.ts +51 -0
- package/dist/types/preview/simulate/extractERC20Transfers.d.ts +1 -1
- package/dist/types/preview/simulate/holders.d.ts +7 -0
- package/dist/types/preview/simulate/index.d.ts +9 -4
- package/dist/types/preview/simulate/simulateFacadeOperation.d.ts +25 -0
- package/dist/types/preview/simulate/simulateOperation.d.ts +20 -0
- package/dist/types/preview/simulate/simulatePoolOpMulticall.d.ts +28 -0
- package/dist/types/preview/simulate/simulatePoolOpV1.d.ts +14 -0
- package/dist/types/preview/simulate/simulatePoolOperation.d.ts +5 -27
- package/dist/types/preview/simulate/types.d.ts +54 -18
- package/dist/types/{history → preview/trace}/errors.d.ts +0 -10
- package/dist/types/preview/trace/extractAdapterCallTraces.d.ts +23 -0
- package/dist/types/{history → preview/trace}/extractTransfers.d.ts +14 -5
- package/dist/types/{history → preview/trace}/findFacadeCalls.d.ts +3 -2
- package/dist/types/preview/trace/index.d.ts +5 -0
- package/dist/types/preview/trace/types.d.ts +21 -0
- package/dist/types/rewards/rewards/api.d.ts +2 -1
- package/dist/types/rewards/rewards/merkl-api.d.ts +2 -1
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +21 -1
- package/dist/types/sdk/accounts/types.d.ts +82 -0
- package/package.json +1 -1
- package/dist/cjs/history/extractProtocolCalls.js +0 -53
- package/dist/esm/history/extractProtocolCalls.js +0 -32
- package/dist/esm/history/trace-utils.js +0 -36
- package/dist/types/history/extractProtocolCalls.d.ts +0 -8
- package/dist/types/history/inner-operations.d.ts +0 -57
- package/dist/types/history/internal-types.d.ts +0 -47
- package/dist/types/history/trace-utils.d.ts +0 -12
- package/dist/types/preview/parse/parseCreditFacadeOperation.d.ts +0 -18
- package/dist/types/preview/parse/parsePoolOperation.d.ts +0 -15
- package/dist/types/preview/simulate/decodeSimulationError.d.ts +0 -18
- /package/dist/esm/{history/inner-operations.js → plugins/adapters/transfers.js} +0 -0
- /package/dist/esm/{history/internal-types.js → preview/parse/types-adapters.js} +0 -0
|
@@ -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 {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
to:
|
|
14
|
-
|
|
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
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
59
|
-
status
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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 "
|
|
7
|
-
import { ierc20Abi } from "
|
|
8
|
-
import { AddressMap } from "
|
|
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
|
|
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
|
-
|
|
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
|
|
30
|
-
if (!
|
|
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 =
|
|
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,
|
|
67
|
+
directTransfers.push({ token, amount: value, from, to });
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
return {
|
|
74
|
-
|
|
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 "
|
|
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",
|
|
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
|
|
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}`;
|