@gearbox-protocol/sdk 14.12.0-next.4 → 14.12.0-next.5
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/preview/index.js +2 -4
- package/dist/cjs/preview/parse/index.js +0 -2
- package/dist/cjs/preview/parse/parseFacadeOperationCalldata.js +5 -12
- package/dist/cjs/preview/parse/parseOperationCalldata.js +5 -3
- package/dist/cjs/preview/parse/parsePoolOperationCalldata.js +4 -0
- package/dist/cjs/preview/parse/parseRWAFactoryOperationCalldata.js +0 -4
- package/dist/cjs/preview/prerequisites/BalancePrerequisite.js +19 -1
- package/dist/cjs/preview/prerequisites/buildPrerequisites.js +24 -15
- package/dist/cjs/preview/{simulate/holders.js → preview/errors.js} +12 -21
- package/dist/cjs/preview/{parse → preview}/extractExpectedBalanceChanges.js +1 -1
- package/dist/cjs/preview/preview/index.js +26 -0
- package/dist/cjs/preview/preview/previewOpenCreditAccount.js +99 -0
- package/dist/cjs/preview/preview/previewOperation.js +41 -0
- package/dist/cjs/preview/preview/previewPoolOperation.js +75 -0
- package/dist/cjs/preview/preview/types.js +16 -0
- package/dist/cjs/preview/simulate/simulatePoolOperation.js +20 -116
- package/dist/cjs/sdk/market/zapper/ZapperContract.js +0 -3
- package/dist/esm/preview/index.js +1 -2
- package/dist/esm/preview/parse/index.js +0 -1
- package/dist/esm/preview/parse/parseFacadeOperationCalldata.js +5 -12
- package/dist/esm/preview/parse/parseOperationCalldata.js +5 -3
- package/dist/esm/preview/parse/parsePoolOperationCalldata.js +4 -0
- package/dist/esm/preview/parse/parseRWAFactoryOperationCalldata.js +0 -4
- package/dist/esm/preview/prerequisites/BalancePrerequisite.js +19 -1
- package/dist/esm/preview/prerequisites/buildPrerequisites.js +28 -16
- package/dist/esm/preview/preview/errors.js +12 -0
- package/dist/esm/preview/{parse → preview}/extractExpectedBalanceChanges.js +1 -1
- package/dist/esm/preview/preview/index.js +3 -0
- package/dist/esm/preview/preview/previewOpenCreditAccount.js +77 -0
- package/dist/esm/preview/preview/previewOperation.js +17 -0
- package/dist/esm/preview/preview/previewPoolOperation.js +53 -0
- package/dist/esm/preview/preview/types.js +0 -0
- package/dist/esm/preview/simulate/simulatePoolOperation.js +21 -120
- package/dist/esm/sdk/market/zapper/ZapperContract.js +0 -3
- package/dist/types/history/types.d.ts +4 -4
- package/dist/types/preview/index.d.ts +1 -2
- package/dist/types/preview/parse/index.d.ts +0 -1
- package/dist/types/preview/parse/types-facades.d.ts +0 -33
- package/dist/types/preview/parse/types-pools.d.ts +29 -1
- package/dist/types/preview/parse/types-rwa.d.ts +1 -13
- package/dist/types/preview/prerequisites/BalancePrerequisite.d.ts +8 -3
- package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +15 -6
- package/dist/types/preview/preview/errors.d.ts +9 -0
- package/dist/types/preview/{parse → preview}/extractExpectedBalanceChanges.d.ts +4 -5
- package/dist/types/preview/preview/index.d.ts +3 -0
- package/dist/types/preview/preview/previewOpenCreditAccount.d.ts +4 -0
- package/dist/types/preview/preview/previewOperation.d.ts +8 -0
- package/dist/types/preview/preview/previewPoolOperation.d.ts +5 -0
- package/dist/types/preview/preview/types.d.ts +103 -0
- package/dist/types/preview/simulate/index.d.ts +1 -1
- package/dist/types/preview/simulate/simulateFacadeOperation.d.ts +0 -2
- package/dist/types/preview/simulate/simulateOperation.d.ts +0 -2
- package/dist/types/preview/simulate/simulatePoolOperation.d.ts +6 -18
- package/dist/types/preview/simulate/simulateRWAOperation.d.ts +0 -2
- package/dist/types/preview/simulate/types.d.ts +12 -26
- package/dist/types/sdk/market/zapper/types.d.ts +6 -6
- package/package.json +1 -1
- package/dist/esm/preview/simulate/holders.js +0 -21
- package/dist/types/preview/simulate/holders.d.ts +0 -7
|
@@ -18,16 +18,12 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var simulatePoolOperation_exports = {};
|
|
20
20
|
__export(simulatePoolOperation_exports, {
|
|
21
|
-
computePoolOpBalanceChanges: () => computePoolOpBalanceChanges,
|
|
22
21
|
simulatePoolOperation: () => simulatePoolOperation
|
|
23
22
|
});
|
|
24
23
|
module.exports = __toCommonJS(simulatePoolOperation_exports);
|
|
25
24
|
var import_generated = require("../../abi/310/generated.js");
|
|
26
|
-
var import_iERC20 = require("../../abi/iERC20.js");
|
|
27
25
|
var import_iZapper = require("../../abi/iZapper.js");
|
|
28
|
-
var import_sdk = require("../../sdk/index.js");
|
|
29
26
|
var import_errors = require("./errors.js");
|
|
30
|
-
var import_holders = require("./holders.js");
|
|
31
27
|
function previewRead(operation) {
|
|
32
28
|
switch (operation.operation) {
|
|
33
29
|
case "Deposit":
|
|
@@ -40,16 +36,6 @@ function previewRead(operation) {
|
|
|
40
36
|
return { functionName: "previewRedeem", amount: operation.shares };
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
|
-
function outsideToken(operation) {
|
|
44
|
-
switch (operation.operation) {
|
|
45
|
-
case "Deposit":
|
|
46
|
-
case "Mint":
|
|
47
|
-
return operation.tokenIn;
|
|
48
|
-
case "Withdraw":
|
|
49
|
-
case "Redeem":
|
|
50
|
-
return operation.tokenOut;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
39
|
function previewContract(operation) {
|
|
54
40
|
const { functionName, amount } = previewRead(operation);
|
|
55
41
|
if (operation.zapper) {
|
|
@@ -67,60 +53,31 @@ function previewContract(operation) {
|
|
|
67
53
|
args: [amount]
|
|
68
54
|
};
|
|
69
55
|
}
|
|
56
|
+
function amountsInOut(operation, previewAmount) {
|
|
57
|
+
switch (operation.operation) {
|
|
58
|
+
case "Deposit":
|
|
59
|
+
return { amountIn: operation.assets, amountOut: previewAmount };
|
|
60
|
+
case "Mint":
|
|
61
|
+
return { amountIn: previewAmount, amountOut: operation.shares };
|
|
62
|
+
case "Withdraw":
|
|
63
|
+
return { amountIn: previewAmount, amountOut: operation.assets };
|
|
64
|
+
case "Redeem":
|
|
65
|
+
return { amountIn: operation.shares, amountOut: previewAmount };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
70
68
|
async function simulatePoolOperation(input, options = {}) {
|
|
71
|
-
const { sdk, operation
|
|
69
|
+
const { sdk, operation } = input;
|
|
72
70
|
const { blockNumber, logger } = options;
|
|
73
|
-
const { pool } = operation;
|
|
74
71
|
try {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
({ holder, token }) => ({
|
|
82
|
-
address: token,
|
|
83
|
-
abi: import_iERC20.ierc20Abi,
|
|
84
|
-
functionName: "balanceOf",
|
|
85
|
-
args: [holder]
|
|
86
|
-
})
|
|
87
|
-
);
|
|
88
|
-
const preview = previewContract(operation);
|
|
89
|
-
let results;
|
|
90
|
-
try {
|
|
91
|
-
results = await sdk.client.multicall({
|
|
92
|
-
allowFailure: false,
|
|
93
|
-
// `undefined` lets viem read at `latest`; `blockNumber` is only set for
|
|
94
|
-
// testnet forks pinned to a specific block.
|
|
95
|
-
blockNumber,
|
|
96
|
-
contracts: [...balanceContracts, preview]
|
|
97
|
-
});
|
|
98
|
-
} catch (cause) {
|
|
99
|
-
throw new import_errors.PreviewSimulationError([
|
|
100
|
-
{
|
|
101
|
-
source: "multicall",
|
|
102
|
-
detail: (0, import_errors.decodeSimulationError)({
|
|
103
|
-
error: cause instanceof Error ? cause : new Error(String(cause))
|
|
104
|
-
})
|
|
105
|
-
}
|
|
106
|
-
]);
|
|
107
|
-
}
|
|
108
|
-
const previewAmount = results[balanceContracts.length];
|
|
109
|
-
const balances = new import_sdk.AddressMap();
|
|
110
|
-
for (const [i, { holder, token }] of balanceCalls.entries()) {
|
|
111
|
-
const tokenBalances = balances.get(holder) ?? new import_sdk.AddressMap();
|
|
112
|
-
tokenBalances.upsert(token, results[i]);
|
|
113
|
-
balances.upsert(holder, tokenBalances);
|
|
114
|
-
}
|
|
115
|
-
const before = (token, holder) => balances.get(holder)?.get(token) ?? 0n;
|
|
72
|
+
const previewAmount = await sdk.client.readContract({
|
|
73
|
+
// `undefined` lets viem read at `latest`; `blockNumber` is only set for
|
|
74
|
+
// testnet forks pinned to a specific block.
|
|
75
|
+
blockNumber,
|
|
76
|
+
...previewContract(operation)
|
|
77
|
+
});
|
|
116
78
|
return {
|
|
117
79
|
status: "success",
|
|
118
|
-
|
|
119
|
-
operation,
|
|
120
|
-
wallet,
|
|
121
|
-
previewAmount,
|
|
122
|
-
before
|
|
123
|
-
)
|
|
80
|
+
...amountsInOut(operation, previewAmount)
|
|
124
81
|
};
|
|
125
82
|
} catch (cause) {
|
|
126
83
|
const error = (0, import_errors.asPreviewSimulationError)(cause, "multicall");
|
|
@@ -128,60 +85,7 @@ async function simulatePoolOperation(input, options = {}) {
|
|
|
128
85
|
return { status: "failure", error };
|
|
129
86
|
}
|
|
130
87
|
}
|
|
131
|
-
function balanceLegs(operation, wallet, previewAmount) {
|
|
132
|
-
const { pool, receiver } = operation;
|
|
133
|
-
switch (operation.operation) {
|
|
134
|
-
case "Deposit":
|
|
135
|
-
return [
|
|
136
|
-
{ address: wallet, token: operation.tokenIn, delta: -operation.assets },
|
|
137
|
-
{ address: receiver, token: pool, delta: previewAmount }
|
|
138
|
-
];
|
|
139
|
-
case "Mint":
|
|
140
|
-
return [
|
|
141
|
-
{ address: wallet, token: operation.tokenIn, delta: -previewAmount },
|
|
142
|
-
{ address: receiver, token: pool, delta: operation.shares }
|
|
143
|
-
];
|
|
144
|
-
case "Withdraw":
|
|
145
|
-
return [
|
|
146
|
-
{ address: operation.owner, token: pool, delta: -previewAmount },
|
|
147
|
-
{
|
|
148
|
-
address: receiver,
|
|
149
|
-
token: operation.tokenOut,
|
|
150
|
-
delta: operation.assets
|
|
151
|
-
}
|
|
152
|
-
];
|
|
153
|
-
case "Redeem":
|
|
154
|
-
return [
|
|
155
|
-
{ address: operation.owner, token: pool, delta: -operation.shares },
|
|
156
|
-
{ address: receiver, token: operation.tokenOut, delta: previewAmount }
|
|
157
|
-
];
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function computePoolOpBalanceChanges(operation, wallet, previewAmount, before) {
|
|
161
|
-
const byAddress = new import_sdk.AddressMap();
|
|
162
|
-
for (const { address, token, delta } of balanceLegs(
|
|
163
|
-
operation,
|
|
164
|
-
wallet,
|
|
165
|
-
previewAmount
|
|
166
|
-
)) {
|
|
167
|
-
const beforeBalance = before(token, address);
|
|
168
|
-
const change = {
|
|
169
|
-
token,
|
|
170
|
-
before: beforeBalance,
|
|
171
|
-
after: beforeBalance + delta,
|
|
172
|
-
delta
|
|
173
|
-
};
|
|
174
|
-
const existing = byAddress.get(address);
|
|
175
|
-
if (existing) {
|
|
176
|
-
existing.changes.push(change);
|
|
177
|
-
} else {
|
|
178
|
-
byAddress.upsert(address, { address, changes: [change] });
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return byAddress.values();
|
|
182
|
-
}
|
|
183
88
|
// Annotate the CommonJS export names for ESM import in node:
|
|
184
89
|
0 && (module.exports = {
|
|
185
|
-
computePoolOpBalanceChanges,
|
|
186
90
|
simulatePoolOperation
|
|
187
91
|
});
|
|
@@ -55,7 +55,6 @@ class ZapperContract extends import_base.BaseContract {
|
|
|
55
55
|
const { rawArgs } = parsed;
|
|
56
56
|
const pool = this.pool;
|
|
57
57
|
const zapper = this.address;
|
|
58
|
-
const token = this.tokenIn.addr;
|
|
59
58
|
const underlying = this.sdk.marketRegister.findByPool(pool).underlying;
|
|
60
59
|
const receiver = rawArgs.receiver;
|
|
61
60
|
if (parsed.functionName.startsWith("deposit")) {
|
|
@@ -65,7 +64,6 @@ class ZapperContract extends import_base.BaseContract {
|
|
|
65
64
|
zapper,
|
|
66
65
|
receiver,
|
|
67
66
|
assets: rawArgs.tokenInAmount ?? value ?? 0n,
|
|
68
|
-
token,
|
|
69
67
|
underlying,
|
|
70
68
|
referralCode: rawArgs.referralCode
|
|
71
69
|
};
|
|
@@ -77,7 +75,6 @@ class ZapperContract extends import_base.BaseContract {
|
|
|
77
75
|
zapper,
|
|
78
76
|
receiver,
|
|
79
77
|
shares: rawArgs.tokenOutAmount,
|
|
80
|
-
token,
|
|
81
78
|
underlying
|
|
82
79
|
};
|
|
83
80
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export * from "./classifyInnerOperations.js";
|
|
2
2
|
export * from "./errors.js";
|
|
3
|
-
export * from "./extractExpectedBalanceChanges.js";
|
|
4
3
|
export * from "./parseFacadeOperationCalldata.js";
|
|
5
4
|
export * from "./parseOperationCalldata.js";
|
|
6
5
|
export * from "./parsePoolOperationCalldata.js";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { isAddressEqual, zeroAddress } from "viem";
|
|
2
2
|
import { classifyInnerOperations } from "./classifyInnerOperations.js";
|
|
3
|
-
import { extractExpectedBalanceChanges } from "./extractExpectedBalanceChanges.js";
|
|
4
3
|
function parseFacadeOperationCalldata(props) {
|
|
5
4
|
const { sdk, facade, calldata } = props;
|
|
6
5
|
const parsed = sdk.parseFunctionDataV2(facade.address, calldata);
|
|
@@ -21,23 +20,20 @@ function parseFacadeOperationCalldata(props) {
|
|
|
21
20
|
sdk,
|
|
22
21
|
underlying: suite.underlying
|
|
23
22
|
});
|
|
24
|
-
const expectedBalanceChanges = extractExpectedBalanceChanges(innerCalls);
|
|
25
23
|
switch (functionName) {
|
|
26
24
|
case "multicall":
|
|
27
25
|
return {
|
|
28
26
|
...metadata,
|
|
29
27
|
operation: "MultiCall",
|
|
30
28
|
creditAccount: rawArgs.creditAccount,
|
|
31
|
-
multicall
|
|
32
|
-
expectedBalanceChanges
|
|
29
|
+
multicall
|
|
33
30
|
};
|
|
34
31
|
case "botMulticall":
|
|
35
32
|
return {
|
|
36
33
|
...metadata,
|
|
37
34
|
operation: "BotMulticall",
|
|
38
35
|
creditAccount: rawArgs.creditAccount,
|
|
39
|
-
multicall
|
|
40
|
-
expectedBalanceChanges
|
|
36
|
+
multicall
|
|
41
37
|
};
|
|
42
38
|
case "openCreditAccount":
|
|
43
39
|
return {
|
|
@@ -46,16 +42,14 @@ function parseFacadeOperationCalldata(props) {
|
|
|
46
42
|
creditAccount: zeroAddress,
|
|
47
43
|
onBehalfOf: rawArgs.onBehalfOf,
|
|
48
44
|
referralCode: rawArgs.referralCode,
|
|
49
|
-
multicall
|
|
50
|
-
expectedBalanceChanges
|
|
45
|
+
multicall
|
|
51
46
|
};
|
|
52
47
|
case "closeCreditAccount":
|
|
53
48
|
return {
|
|
54
49
|
...metadata,
|
|
55
50
|
operation: "CloseCreditAccount",
|
|
56
51
|
creditAccount: rawArgs.creditAccount,
|
|
57
|
-
multicall
|
|
58
|
-
expectedBalanceChanges
|
|
52
|
+
multicall
|
|
59
53
|
};
|
|
60
54
|
case "liquidateCreditAccount":
|
|
61
55
|
return {
|
|
@@ -67,8 +61,7 @@ function parseFacadeOperationCalldata(props) {
|
|
|
67
61
|
// liquidation, so they are not recoverable from raw calldata.
|
|
68
62
|
token: zeroAddress,
|
|
69
63
|
remainingFunds: 0n,
|
|
70
|
-
multicall
|
|
71
|
-
expectedBalanceChanges
|
|
64
|
+
multicall
|
|
72
65
|
};
|
|
73
66
|
case "partiallyLiquidateCreditAccount":
|
|
74
67
|
return {
|
|
@@ -23,7 +23,8 @@ function parseOperationCalldata(input) {
|
|
|
23
23
|
receiver: parsed.receiver,
|
|
24
24
|
assets: parsed.assets,
|
|
25
25
|
underlying: parsed.underlying,
|
|
26
|
-
tokenIn:
|
|
26
|
+
tokenIn: contract.tokenIn.addr,
|
|
27
|
+
tokenOut: contract.tokenOut.addr,
|
|
27
28
|
zapper: parsed.zapper,
|
|
28
29
|
referralCode: parsed.referralCode
|
|
29
30
|
};
|
|
@@ -33,12 +34,13 @@ function parseOperationCalldata(input) {
|
|
|
33
34
|
operation: "Redeem",
|
|
34
35
|
pool: parsed.pool,
|
|
35
36
|
receiver: parsed.receiver,
|
|
36
|
-
// The zapper burns the caller's
|
|
37
|
+
// The zapper burns the caller's share tokens, so the share owner is the
|
|
37
38
|
// transaction sender.
|
|
38
39
|
owner: sender,
|
|
39
40
|
shares: parsed.shares,
|
|
40
41
|
underlying: parsed.underlying,
|
|
41
|
-
|
|
42
|
+
tokenIn: contract.tokenOut.addr,
|
|
43
|
+
tokenOut: contract.tokenIn.addr,
|
|
42
44
|
zapper: parsed.zapper
|
|
43
45
|
};
|
|
44
46
|
return op;
|
|
@@ -15,6 +15,7 @@ function parsePoolOperationCalldata(props) {
|
|
|
15
15
|
assets: rawArgs.assets,
|
|
16
16
|
underlying,
|
|
17
17
|
tokenIn: underlying,
|
|
18
|
+
tokenOut: pool.address,
|
|
18
19
|
zapper: void 0,
|
|
19
20
|
referralCode: functionName === "depositWithReferral" ? rawArgs.referralCode : void 0
|
|
20
21
|
};
|
|
@@ -27,6 +28,7 @@ function parsePoolOperationCalldata(props) {
|
|
|
27
28
|
shares: rawArgs.shares,
|
|
28
29
|
underlying,
|
|
29
30
|
tokenIn: underlying,
|
|
31
|
+
tokenOut: pool.address,
|
|
30
32
|
zapper: void 0,
|
|
31
33
|
referralCode: functionName === "mintWithReferral" ? rawArgs.referralCode : void 0
|
|
32
34
|
};
|
|
@@ -38,6 +40,7 @@ function parsePoolOperationCalldata(props) {
|
|
|
38
40
|
owner: rawArgs.owner,
|
|
39
41
|
assets: rawArgs.assets,
|
|
40
42
|
underlying,
|
|
43
|
+
tokenIn: pool.address,
|
|
41
44
|
tokenOut: underlying,
|
|
42
45
|
zapper: void 0
|
|
43
46
|
};
|
|
@@ -49,6 +52,7 @@ function parsePoolOperationCalldata(props) {
|
|
|
49
52
|
owner: rawArgs.owner,
|
|
50
53
|
shares: rawArgs.shares,
|
|
51
54
|
underlying,
|
|
55
|
+
tokenIn: pool.address,
|
|
52
56
|
tokenOut: underlying,
|
|
53
57
|
zapper: void 0
|
|
54
58
|
};
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
RWA_FACTORY_SECURITIZE
|
|
7
7
|
} from "../../sdk/index.js";
|
|
8
8
|
import { classifyInnerOperations } from "./classifyInnerOperations.js";
|
|
9
|
-
import { extractExpectedBalanceChanges } from "./extractExpectedBalanceChanges.js";
|
|
10
9
|
function parseRWAFactoryOperationCalldata(props) {
|
|
11
10
|
const { contractType, address } = props.factory;
|
|
12
11
|
if (isRWAFactory(props.factory, RWA_FACTORY_SECURITIZE)) {
|
|
@@ -38,14 +37,12 @@ function parseSecuritizeOperationCalldata(props) {
|
|
|
38
37
|
sdk,
|
|
39
38
|
underlying: suite.underlying
|
|
40
39
|
});
|
|
41
|
-
const expectedBalanceChanges = extractExpectedBalanceChanges(innerCalls);
|
|
42
40
|
switch (functionName) {
|
|
43
41
|
case "openCreditAccount":
|
|
44
42
|
return {
|
|
45
43
|
...metadata,
|
|
46
44
|
operation: "SecuritizeOpenCreditAccount",
|
|
47
45
|
multicall,
|
|
48
|
-
expectedBalanceChanges,
|
|
49
46
|
tokensToRegister,
|
|
50
47
|
signaturesToCache
|
|
51
48
|
};
|
|
@@ -55,7 +52,6 @@ function parseSecuritizeOperationCalldata(props) {
|
|
|
55
52
|
operation: "SecuritizeMulticall",
|
|
56
53
|
creditAccount: rawArgs.creditAccount,
|
|
57
54
|
multicall,
|
|
58
|
-
expectedBalanceChanges,
|
|
59
55
|
tokensToRegister,
|
|
60
56
|
signaturesToCache
|
|
61
57
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { erc20Abi } from "viem";
|
|
2
|
+
import { iMulticall3Abi } from "../../abi/iMulticall3.js";
|
|
3
|
+
import { hexEq, NATIVE_ADDRESS } from "../../sdk/index.js";
|
|
2
4
|
import {
|
|
3
5
|
Prerequisite,
|
|
4
6
|
toPrerequisiteError
|
|
@@ -29,7 +31,23 @@ class BalancePrerequisite extends Prerequisite {
|
|
|
29
31
|
get detail() {
|
|
30
32
|
return this.#detail;
|
|
31
33
|
}
|
|
32
|
-
calls() {
|
|
34
|
+
calls(ctx) {
|
|
35
|
+
if (hexEq(this.#detail.token, NATIVE_ADDRESS)) {
|
|
36
|
+
const multicall3 = ctx.sdk.client.chain.contracts?.multicall3?.address;
|
|
37
|
+
if (!multicall3) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
"multicall3 is not configured for this chain, cannot read native balance"
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
address: multicall3,
|
|
45
|
+
abi: iMulticall3Abi,
|
|
46
|
+
functionName: "getEthBalance",
|
|
47
|
+
args: [this.#detail.owner]
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
}
|
|
33
51
|
return [
|
|
34
52
|
{
|
|
35
53
|
address: this.#detail.token,
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { isAddressEqual } from "viem";
|
|
2
2
|
import {
|
|
3
|
-
AddressSet
|
|
3
|
+
AddressSet,
|
|
4
|
+
NATIVE_ADDRESS
|
|
4
5
|
} from "../../sdk/index.js";
|
|
6
|
+
import {
|
|
7
|
+
parseOperationCalldata
|
|
8
|
+
} from "../parse/parseOperationCalldata.js";
|
|
5
9
|
import { AllowancePrerequisite } from "./AllowancePrerequisite.js";
|
|
6
10
|
import { BalancePrerequisite } from "./BalancePrerequisite.js";
|
|
7
11
|
import { RWAOpenRequirementsPrerequisite } from "./RWAOpenRequirementsPrerequisite.js";
|
|
8
|
-
async function buildPrerequisites(
|
|
9
|
-
const { wallet } =
|
|
12
|
+
async function buildPrerequisites(input) {
|
|
13
|
+
const { sdk, sender: wallet, blockNumber } = input;
|
|
14
|
+
const tx = parseOperationCalldata(input);
|
|
15
|
+
const ctx = { sdk, wallet, blockNumber };
|
|
10
16
|
switch (tx.operation) {
|
|
11
17
|
// Deposit and Mint both pull the underlying from the caller into the pool;
|
|
12
18
|
// they only differ in which side (assets vs shares) the caller specifies.
|
|
@@ -16,21 +22,27 @@ async function buildPrerequisites(tx, ctx) {
|
|
|
16
22
|
// not knowable from calldata alone).
|
|
17
23
|
case "Deposit":
|
|
18
24
|
if (tx.zapper) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const prereqs = [];
|
|
26
|
+
if (!isAddressEqual(tx.tokenIn, NATIVE_ADDRESS)) {
|
|
27
|
+
prereqs.push(
|
|
28
|
+
new AllowancePrerequisite({
|
|
29
|
+
token: tx.tokenIn,
|
|
30
|
+
owner: wallet,
|
|
31
|
+
spender: tx.zapper,
|
|
32
|
+
required: tx.assets,
|
|
33
|
+
title: "Token approved to zapper"
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
prereqs.push(
|
|
27
38
|
new BalancePrerequisite({
|
|
28
39
|
token: tx.tokenIn,
|
|
29
40
|
owner: wallet,
|
|
30
41
|
required: tx.assets,
|
|
31
42
|
title: "Sufficient token balance"
|
|
32
43
|
})
|
|
33
|
-
|
|
44
|
+
);
|
|
45
|
+
return prereqs;
|
|
34
46
|
}
|
|
35
47
|
return [
|
|
36
48
|
new AllowancePrerequisite({
|
|
@@ -69,17 +81,17 @@ async function buildPrerequisites(tx, ctx) {
|
|
|
69
81
|
if (tx.zapper) {
|
|
70
82
|
return [
|
|
71
83
|
new BalancePrerequisite({
|
|
72
|
-
token: tx.
|
|
84
|
+
token: tx.tokenIn,
|
|
73
85
|
owner: wallet,
|
|
74
86
|
required: tx.shares,
|
|
75
|
-
title: "Sufficient
|
|
87
|
+
title: "Sufficient share token balance"
|
|
76
88
|
}),
|
|
77
89
|
new AllowancePrerequisite({
|
|
78
|
-
token: tx.
|
|
90
|
+
token: tx.tokenIn,
|
|
79
91
|
owner: wallet,
|
|
80
92
|
spender: tx.zapper,
|
|
81
93
|
required: tx.shares,
|
|
82
|
-
title: "
|
|
94
|
+
title: "Share token approved to zapper"
|
|
83
95
|
})
|
|
84
96
|
];
|
|
85
97
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class UnsupportedOperationError extends Error {
|
|
2
|
+
/** The parsed operation kind (the `operation` discriminant). */
|
|
3
|
+
operation;
|
|
4
|
+
constructor(operation) {
|
|
5
|
+
super(`operation "${operation}" is not supported by previewOperation`);
|
|
6
|
+
this.name = "UnsupportedOperationError";
|
|
7
|
+
this.operation = operation;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
UnsupportedOperationError
|
|
12
|
+
};
|
|
@@ -14,7 +14,7 @@ function extractExpectedBalanceChanges(innerCalls) {
|
|
|
14
14
|
if (!balanceDeltas) {
|
|
15
15
|
return void 0;
|
|
16
16
|
}
|
|
17
|
-
return balanceDeltas.map(({ token, amount }) => ({ token,
|
|
17
|
+
return balanceDeltas.map(({ token, amount }) => ({ token, balance: amount }));
|
|
18
18
|
}
|
|
19
19
|
function functionName(call) {
|
|
20
20
|
return call.functionName.split("(")[0];
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AddressMap
|
|
3
|
+
} from "../../sdk/index.js";
|
|
4
|
+
import { extractExpectedBalanceChanges } from "./extractExpectedBalanceChanges.js";
|
|
5
|
+
function previewOpenCreditAccount(input, operation) {
|
|
6
|
+
const { sdk, to, calldata } = input;
|
|
7
|
+
const market = sdk.marketRegister.findByCreditManager(
|
|
8
|
+
operation.creditManager
|
|
9
|
+
);
|
|
10
|
+
const collateralByToken = new AddressMap();
|
|
11
|
+
const balances = new AddressMap();
|
|
12
|
+
const addBalance = (token, amount) => {
|
|
13
|
+
balances.upsert(token, (balances.get(token) ?? 0n) + amount);
|
|
14
|
+
};
|
|
15
|
+
let debt = 0n;
|
|
16
|
+
const quotas = [];
|
|
17
|
+
for (const op of operation.multicall) {
|
|
18
|
+
switch (op.operation) {
|
|
19
|
+
case "AddCollateral": {
|
|
20
|
+
const balance = collateralByToken.get(op.token)?.balance ?? 0n;
|
|
21
|
+
collateralByToken.upsert(op.token, {
|
|
22
|
+
token: op.token,
|
|
23
|
+
balance: balance + op.amount
|
|
24
|
+
});
|
|
25
|
+
addBalance(op.token, op.amount);
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case "WithdrawCollateral":
|
|
29
|
+
addBalance(op.token, -op.amount);
|
|
30
|
+
break;
|
|
31
|
+
case "IncreaseBorrowedAmount":
|
|
32
|
+
debt += op.amount;
|
|
33
|
+
addBalance(op.token, op.amount);
|
|
34
|
+
break;
|
|
35
|
+
case "DecreaseBorrowedAmount":
|
|
36
|
+
debt -= op.amount;
|
|
37
|
+
addBalance(op.token, -op.amount);
|
|
38
|
+
break;
|
|
39
|
+
case "UpdateQuota":
|
|
40
|
+
quotas.push({ token: op.token, balance: op.change });
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const collateral = collateralByToken.values();
|
|
45
|
+
const collateralValue = collateral.reduce(
|
|
46
|
+
(acc, { token, balance }) => acc + market.priceOracle.convert(token, market.underlying, balance),
|
|
47
|
+
0n
|
|
48
|
+
);
|
|
49
|
+
const parsed = sdk.parseFunctionDataV2(to, calldata);
|
|
50
|
+
const innerCalls = parsed.rawArgs.calls ?? [];
|
|
51
|
+
const deltas = extractExpectedBalanceChanges(innerCalls) ?? [];
|
|
52
|
+
for (const { token, balance } of deltas) {
|
|
53
|
+
addBalance(token, balance);
|
|
54
|
+
}
|
|
55
|
+
const assets = balances.entries().filter(([, balance]) => balance > 1n).map(([token, balance]) => ({ token, balance }));
|
|
56
|
+
return {
|
|
57
|
+
operation: operation.operation,
|
|
58
|
+
target: inferTargetAsset(operation.multicall, balances),
|
|
59
|
+
collateral,
|
|
60
|
+
collateralValue,
|
|
61
|
+
debt,
|
|
62
|
+
quotas,
|
|
63
|
+
assets
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function inferTargetAsset(multicall, balances) {
|
|
67
|
+
for (const op of multicall) {
|
|
68
|
+
if (op.operation === "UpdateQuota" && op.change > 0n) {
|
|
69
|
+
const balance = balances.get(op.token);
|
|
70
|
+
return balance ? { token: op.token, balance } : void 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return void 0;
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
previewOpenCreditAccount
|
|
77
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { isPoolOperation, parseOperationCalldata } from "../parse/index.js";
|
|
2
|
+
import { UnsupportedOperationError } from "./errors.js";
|
|
3
|
+
import { previewOpenCreditAccount } from "./previewOpenCreditAccount.js";
|
|
4
|
+
import { previewPoolOperation } from "./previewPoolOperation.js";
|
|
5
|
+
async function previewOperation(input, options) {
|
|
6
|
+
const operation = parseOperationCalldata(input);
|
|
7
|
+
if (isPoolOperation(operation)) {
|
|
8
|
+
return previewPoolOperation(input, operation, options);
|
|
9
|
+
}
|
|
10
|
+
if (operation.operation === "OpenCreditAccount" || operation.operation === "SecuritizeOpenCreditAccount") {
|
|
11
|
+
return previewOpenCreditAccount(input, operation);
|
|
12
|
+
}
|
|
13
|
+
throw new UnsupportedOperationError(operation.operation);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
previewOperation
|
|
17
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
simulatePoolOperation
|
|
3
|
+
} from "../simulate/index.js";
|
|
4
|
+
async function previewPoolOperation(input, operation, options) {
|
|
5
|
+
const { sdk, to, calldata } = input;
|
|
6
|
+
const { tokenIn, tokenOut } = operation;
|
|
7
|
+
const sim = await simulatePoolOperation(
|
|
8
|
+
{ sdk, operation, to, calldata },
|
|
9
|
+
options
|
|
10
|
+
);
|
|
11
|
+
if (sim.status === "success") {
|
|
12
|
+
return {
|
|
13
|
+
operation: operation.operation,
|
|
14
|
+
pool: operation.pool,
|
|
15
|
+
tokenIn: { token: tokenIn, balance: sim.amountIn },
|
|
16
|
+
tokenOut: { token: tokenOut, balance: sim.amountOut }
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const { error } = sim;
|
|
20
|
+
switch (operation.operation) {
|
|
21
|
+
case "Deposit":
|
|
22
|
+
return {
|
|
23
|
+
operation: "Deposit",
|
|
24
|
+
pool: operation.pool,
|
|
25
|
+
tokenIn: { token: tokenIn, balance: operation.assets },
|
|
26
|
+
tokenOut: { token: tokenOut, error }
|
|
27
|
+
};
|
|
28
|
+
case "Mint":
|
|
29
|
+
return {
|
|
30
|
+
operation: "Mint",
|
|
31
|
+
pool: operation.pool,
|
|
32
|
+
tokenIn: { token: tokenIn, error },
|
|
33
|
+
tokenOut: { token: tokenOut, balance: operation.shares }
|
|
34
|
+
};
|
|
35
|
+
case "Withdraw":
|
|
36
|
+
return {
|
|
37
|
+
operation: "Withdraw",
|
|
38
|
+
pool: operation.pool,
|
|
39
|
+
tokenIn: { token: tokenIn, error },
|
|
40
|
+
tokenOut: { token: tokenOut, balance: operation.assets }
|
|
41
|
+
};
|
|
42
|
+
case "Redeem":
|
|
43
|
+
return {
|
|
44
|
+
operation: "Redeem",
|
|
45
|
+
pool: operation.pool,
|
|
46
|
+
tokenIn: { token: tokenIn, balance: operation.shares },
|
|
47
|
+
tokenOut: { token: tokenOut, error }
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
previewPoolOperation
|
|
53
|
+
};
|
|
File without changes
|