@gearbox-protocol/sdk 16.0.0-next.11 → 16.0.0-next.13
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/dev/mode-parity/comparePositions.js +3 -2
- package/dist/cjs/dev/mode-parity/compareRules.js +12 -1
- package/dist/cjs/dev/mode-parity/scriptUtils.js +1 -1
- package/dist/cjs/model/compare.schema.js +8 -0
- package/dist/cjs/model/index.js +3 -1
- package/dist/cjs/model/positions.js +6 -0
- package/dist/cjs/model/positions.schema.js +4 -3
- package/dist/cjs/model/previews.js +4 -3
- package/dist/cjs/onchain/market/adapters/contracts/AbstractAdapter.js +14 -0
- package/dist/cjs/onchain/market/adapters/contracts/ERC4626AdapterContract.js +54 -0
- package/dist/cjs/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +13 -0
- package/dist/cjs/onchain/positions/PositionsService.js +20 -17
- package/dist/cjs/preview/preview/replayInnerOperations.js +10 -25
- package/dist/esm/dev/mode-parity/comparePositions.js +3 -2
- package/dist/esm/dev/mode-parity/compareRules.js +12 -1
- package/dist/esm/dev/mode-parity/scriptUtils.js +1 -1
- package/dist/esm/model/compare.schema.js +8 -1
- package/dist/esm/model/index.js +4 -4
- package/dist/esm/model/positions.js +6 -1
- package/dist/esm/model/positions.schema.js +5 -4
- package/dist/esm/model/previews.js +4 -3
- package/dist/esm/onchain/market/adapters/contracts/AbstractAdapter.js +14 -0
- package/dist/esm/onchain/market/adapters/contracts/ERC4626AdapterContract.js +55 -1
- package/dist/esm/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +14 -1
- package/dist/esm/onchain/positions/PositionsService.js +21 -18
- package/dist/esm/preview/preview/replayInnerOperations.js +11 -26
- package/dist/types/dev/mode-parity/comparePositions.d.ts +5 -3
- package/dist/types/dev/mode-parity/fieldDiff.d.ts +3 -1
- package/dist/types/model/compare.schema.d.ts +9 -2
- package/dist/types/model/index.d.ts +4 -4
- package/dist/types/model/positions.d.ts +19 -1
- package/dist/types/model/positions.schema.d.ts +2 -0
- package/dist/types/model/previews.d.ts +4 -3
- package/dist/types/onchain/market/adapters/contracts/AbstractAdapter.d.ts +12 -0
- package/dist/types/onchain/market/adapters/contracts/ERC4626AdapterContract.d.ts +8 -1
- package/dist/types/onchain/market/adapters/contracts/MidasGatewayAdapterContract.d.ts +7 -0
- package/package.json +1 -1
- package/dist/cjs/preview/preview/applyRWAWrapUnwrap.js +0 -67
- package/dist/esm/preview/preview/applyRWAWrapUnwrap.js +0 -66
- package/dist/types/preview/preview/applyRWAWrapUnwrap.d.ts +0 -17
|
@@ -15,8 +15,9 @@ const tagDiff = require_dev_mode_parity_compareRules.makeTagDiff({
|
|
|
15
15
|
* Matches two position listings per wallet by {@link positionId} and reports
|
|
16
16
|
* every field the two sources disagree on.
|
|
17
17
|
*
|
|
18
|
-
* Nothing is filtered out. A field only one mode can fill,
|
|
19
|
-
*
|
|
18
|
+
* Nothing is filtered out. A field only one mode can fill, a strategy field
|
|
19
|
+
* both-mode merge overlays from the backend, or a USD value that drifted
|
|
20
|
+
* within snapshot-lag noise, is still reported — tagged
|
|
20
21
|
* {@link FieldDiff.expected} so that {@link CompareCounts.clean} can ignore it
|
|
21
22
|
* while {@link CompareCounts.identical} stays strict.
|
|
22
23
|
**/
|
|
@@ -25,15 +25,26 @@ function makeTagDiff(rulesByKind) {
|
|
|
25
25
|
if (!rules) return diff;
|
|
26
26
|
const path = require_dev_mode_parity_fieldDiff.collapseArrayKeys(diff.path);
|
|
27
27
|
if (isModeScoped(path, rules)) return require_dev_mode_parity_fieldDiff.withExpected(diff, "mode-scoped");
|
|
28
|
+
if (isBackendPreferred(path, rules)) return require_dev_mode_parity_fieldDiff.withExpected(diff, "backend-preferred");
|
|
28
29
|
const tag = rules.get(path);
|
|
29
30
|
if (tag && typeof tag === "object" && withinTolerance(tag.tolerance, diff)) return require_dev_mode_parity_fieldDiff.withExpected(diff, "tolerance");
|
|
30
31
|
return diff;
|
|
31
32
|
};
|
|
32
33
|
}
|
|
34
|
+
function pathMatchesRule(path, rulePath) {
|
|
35
|
+
return path === rulePath || path.startsWith(`${rulePath}.`) || path.startsWith(`${rulePath}[`);
|
|
36
|
+
}
|
|
33
37
|
function isModeScoped(path, rules) {
|
|
34
38
|
for (const [rulePath, tag] of rules) {
|
|
35
39
|
if (tag !== "offchainOnly" && tag !== "onchainOnly") continue;
|
|
36
|
-
if (path
|
|
40
|
+
if (pathMatchesRule(path, rulePath)) return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
function isBackendPreferred(path, rules) {
|
|
45
|
+
for (const [rulePath, tag] of rules) {
|
|
46
|
+
if (tag !== "backendPreferred") continue;
|
|
47
|
+
if (pathMatchesRule(path, rulePath)) return true;
|
|
37
48
|
}
|
|
38
49
|
return false;
|
|
39
50
|
}
|
|
@@ -108,7 +108,7 @@ function printCompareSummary(noun, report, extraLines = []) {
|
|
|
108
108
|
})));
|
|
109
109
|
}
|
|
110
110
|
if (expected.length) {
|
|
111
|
-
console.log("\nexpected fields (mode-scoped or within tolerance):");
|
|
111
|
+
console.log("\nexpected fields (mode-scoped, backend-preferred, or within tolerance):");
|
|
112
112
|
console.table(expected.slice(0, 25).map((entry) => ({
|
|
113
113
|
field: entry.path,
|
|
114
114
|
rows: entry.expected,
|
|
@@ -13,6 +13,13 @@ function onchainOnly(schema) {
|
|
|
13
13
|
return schema.meta({ compare: "onchainOnly" });
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
+
* Marks a field whose backend value both-mode merge overlays onto the chain
|
|
17
|
+
* row, so a source disagreement is expected.
|
|
18
|
+
**/
|
|
19
|
+
function backendPreferred(schema) {
|
|
20
|
+
return schema.meta({ compare: "backendPreferred" });
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
16
23
|
* Marks a numeric field whose two sources may drift within {@link kind}.
|
|
17
24
|
**/
|
|
18
25
|
function tolerance(schema, kind) {
|
|
@@ -27,6 +34,7 @@ function compareTagOf(schema) {
|
|
|
27
34
|
return meta.compare;
|
|
28
35
|
}
|
|
29
36
|
//#endregion
|
|
37
|
+
exports.backendPreferred = backendPreferred;
|
|
30
38
|
exports.compareTagOf = compareTagOf;
|
|
31
39
|
exports.offchainOnly = offchainOnly;
|
|
32
40
|
exports.onchainOnly = onchainOnly;
|
package/dist/cjs/model/index.js
CHANGED
|
@@ -28,16 +28,18 @@ exports.ERROR_INVALID_TRANSACTION_VALUE = require_model_previews.ERROR_INVALID_T
|
|
|
28
28
|
exports.ERROR_MALFORMED_BRACKET = require_model_previews.ERROR_MALFORMED_BRACKET;
|
|
29
29
|
exports.ERROR_NON_ADAPTER_CALL_IN_BRACKET = require_model_previews.ERROR_NON_ADAPTER_CALL_IN_BRACKET;
|
|
30
30
|
exports.ERROR_UNPREVIEWABLE_ADAPTER_CALL = require_model_previews.ERROR_UNPREVIEWABLE_ADAPTER_CALL;
|
|
31
|
-
exports.ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP = require_model_previews.ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP;
|
|
32
31
|
exports.ERROR_UNPRICEABLE_TOKEN = require_model_previews.ERROR_UNPRICEABLE_TOKEN;
|
|
32
|
+
exports.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = require_model_previews.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL;
|
|
33
33
|
exports.FILTER_ALL = require_model_filters.FILTER_ALL;
|
|
34
34
|
exports.POOL_OPPORTUNITY_CHART_METRICS = require_model_charts.POOL_OPPORTUNITY_CHART_METRICS;
|
|
35
35
|
exports.POOL_POSITION_CHART_METRICS = require_model_charts.POOL_POSITION_CHART_METRICS;
|
|
36
36
|
exports.STRATEGY_OPPORTUNITY_CHART_METRICS = require_model_charts.STRATEGY_OPPORTUNITY_CHART_METRICS;
|
|
37
37
|
exports.STRATEGY_POSITION_CHART_METRICS = require_model_charts.STRATEGY_POSITION_CHART_METRICS;
|
|
38
|
+
exports.STRATEGY_POSITION_COLLATERAL_ERROR = require_model_positions.STRATEGY_POSITION_COLLATERAL_ERROR;
|
|
38
39
|
exports.amountSchema = require_model_primitives_schema.amountSchema;
|
|
39
40
|
exports.apyBreakdownSchema = require_model_opportunities_schema.apyBreakdownSchema;
|
|
40
41
|
exports.assetTypeSchema = require_model_primitives_schema.assetTypeSchema;
|
|
42
|
+
exports.backendPreferred = require_model_compare_schema.backendPreferred;
|
|
41
43
|
exports.booleanParamSchema = require_model_filters_schema.booleanParamSchema;
|
|
42
44
|
exports.borrowRateBreakdownSchema = require_model_positions_schema.borrowRateBreakdownSchema;
|
|
43
45
|
exports.bpsSchema = require_model_primitives_schema.bpsSchema;
|
|
@@ -2,6 +2,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_model_filters = require("./filters.js");
|
|
3
3
|
//#region src/model/positions.ts
|
|
4
4
|
/**
|
|
5
|
+
* Set on {@link StrategyPosition.error} when the account could not be fully
|
|
6
|
+
* valued (e.g. a dead price feed).
|
|
7
|
+
**/
|
|
8
|
+
const STRATEGY_POSITION_COLLATERAL_ERROR = "collateral computation failed";
|
|
9
|
+
/**
|
|
5
10
|
* Builds the canonical id of a pool position.
|
|
6
11
|
*
|
|
7
12
|
* @example
|
|
@@ -85,6 +90,7 @@ function positionUnderlying(position) {
|
|
|
85
90
|
}
|
|
86
91
|
}
|
|
87
92
|
//#endregion
|
|
93
|
+
exports.STRATEGY_POSITION_COLLATERAL_ERROR = STRATEGY_POSITION_COLLATERAL_ERROR;
|
|
88
94
|
exports.liquidationPositionId = liquidationPositionId;
|
|
89
95
|
exports.matchesPositionFilter = matchesPositionFilter;
|
|
90
96
|
exports.poolPositionId = poolPositionId;
|
|
@@ -96,12 +96,12 @@ const borrowRateBreakdownSchema = zod_v4.z.object({
|
|
|
96
96
|
**/
|
|
97
97
|
const strategyPositionSchema = zod_v4.z.object({
|
|
98
98
|
kind: zod_v4.z.literal("strategy"),
|
|
99
|
-
name: zod_v4.z.string(),
|
|
99
|
+
name: require_model_compare_schema.backendPreferred(zod_v4.z.string()),
|
|
100
100
|
chainId: require_model_primitives_schema.chainIdSchema,
|
|
101
101
|
creditManager: require_onchain_utils_zod.ZodAddress(),
|
|
102
102
|
creditAccount: require_onchain_utils_zod.ZodAddress(),
|
|
103
103
|
underlyingToken: require_model_primitives_schema.underlyingTokenSchema,
|
|
104
|
-
targetCollateral: require_model_primitives_schema.tokenSchema.nullable(),
|
|
104
|
+
targetCollateral: require_model_compare_schema.backendPreferred(require_model_primitives_schema.tokenSchema.nullable()),
|
|
105
105
|
leverage: require_model_compare_schema.tolerance(require_model_primitives_schema.leverageSchema, "float"),
|
|
106
106
|
borrowApy: require_model_compare_schema.tolerance(require_model_primitives_schema.bpsSchema, "bps"),
|
|
107
107
|
borrowApyAvg7D: require_model_compare_schema.offchainOnly(require_model_primitives_schema.bpsSchema).optional(),
|
|
@@ -115,7 +115,8 @@ const strategyPositionSchema = zod_v4.z.object({
|
|
|
115
115
|
timeToLiquidation: require_model_compare_schema.onchainOnly(require_onchain_utils_zod.ZodBigInt().nullable()).optional(),
|
|
116
116
|
liquidationPrice: require_model_compare_schema.onchainOnly(require_onchain_utils_zod.ZodBigInt().nullable()).optional(),
|
|
117
117
|
pnl: require_model_compare_schema.offchainOnly(pnlBreakdownSchema).optional(),
|
|
118
|
-
collaterals: zod_v4.z.array(positionCollateralSchema)
|
|
118
|
+
collaterals: zod_v4.z.array(positionCollateralSchema),
|
|
119
|
+
error: zod_v4.z.string().optional()
|
|
119
120
|
});
|
|
120
121
|
/**
|
|
121
122
|
* {@link Position}
|
|
@@ -21,9 +21,10 @@ const ERROR_NON_ADAPTER_CALL_IN_BRACKET = 1003;
|
|
|
21
21
|
**/
|
|
22
22
|
const ERROR_UNPREVIEWABLE_ADAPTER_CALL = 1004;
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* An out-of-bracket adapter call that is allowed there (e.g. RWA wrap/unwrap)
|
|
25
|
+
* could not be decoded or replayed
|
|
25
26
|
**/
|
|
26
|
-
const
|
|
27
|
+
const ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = 1005;
|
|
27
28
|
/**
|
|
28
29
|
* `msg.value` does not fit into the declared WETH collateral
|
|
29
30
|
* Transactions can have arbitrary value, but the ones that we create
|
|
@@ -38,5 +39,5 @@ exports.ERROR_INVALID_TRANSACTION_VALUE = ERROR_INVALID_TRANSACTION_VALUE;
|
|
|
38
39
|
exports.ERROR_MALFORMED_BRACKET = ERROR_MALFORMED_BRACKET;
|
|
39
40
|
exports.ERROR_NON_ADAPTER_CALL_IN_BRACKET = ERROR_NON_ADAPTER_CALL_IN_BRACKET;
|
|
40
41
|
exports.ERROR_UNPREVIEWABLE_ADAPTER_CALL = ERROR_UNPREVIEWABLE_ADAPTER_CALL;
|
|
41
|
-
exports.ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP = ERROR_UNPREVIEWABLE_RWA_WRAP_UNWRAP;
|
|
42
42
|
exports.ERROR_UNPRICEABLE_TOKEN = ERROR_UNPRICEABLE_TOKEN;
|
|
43
|
+
exports.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL;
|
|
@@ -115,6 +115,20 @@ var AbstractAdapterContract = class extends require_onchain_base_BaseContract.Ba
|
|
|
115
115
|
await this.applyBalanceChanges(balances, decoded);
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
118
|
+
* Replays this adapter call when it appears outside a
|
|
119
|
+
* storeExpectedBalances/compareBalances bracket, mutating `balances` in
|
|
120
|
+
* place, and returns `true` when the call is legal there.
|
|
121
|
+
*
|
|
122
|
+
* Base implementation returns `false`: nothing enforces the outcome of an
|
|
123
|
+
* out-of-bracket adapter call on-chain, so it cannot be previewed.
|
|
124
|
+
*
|
|
125
|
+
* @throws when the call is allowed outside a bracket but its calldata
|
|
126
|
+
* cannot be decoded
|
|
127
|
+
*/
|
|
128
|
+
replayOutOfBracketCall(_balances, _calldata) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
118
132
|
* Applies the balance changes of a decoded adapter call to the running
|
|
119
133
|
* balances, mutating them in place. Overrides should express changes via
|
|
120
134
|
* {@link setLeftover} (diff-style calls) and {@link spendExact}
|
|
@@ -98,6 +98,60 @@ var ERC4626AdapterContract = class extends require_onchain_market_adapters_contr
|
|
|
98
98
|
};
|
|
99
99
|
return super.classifyLegacyOperation(parsed, transfers);
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Out-of-bracket calls are legal only on the RWA wrap/unwrap adapter (the
|
|
103
|
+
* share converts 1:1 with the vault asset, so no on-chain preview or
|
|
104
|
+
* slippage bracket is needed); a regular vault-strategy ERC4626 adapter
|
|
105
|
+
* keeps the base behavior and returns false.
|
|
106
|
+
*/
|
|
107
|
+
replayOutOfBracketCall(balances, calldata) {
|
|
108
|
+
const meta = this.sdk.tokensMeta.get(this.share);
|
|
109
|
+
if (!meta || !this.sdk.tokensMeta.isRWAUnderlying(meta)) return false;
|
|
110
|
+
const resolved = this.#resolveWrapUnwrap(calldata, balances);
|
|
111
|
+
if (resolved && resolved.amountIn > 0n) {
|
|
112
|
+
balances.dec(resolved.tokenIn, resolved.amountIn);
|
|
113
|
+
balances.inc(resolved.tokenOut, resolved.amountIn);
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
#resolveWrapUnwrap(calldata, balances) {
|
|
118
|
+
const decoded = (0, viem.decodeFunctionData)({
|
|
119
|
+
abi,
|
|
120
|
+
data: calldata
|
|
121
|
+
});
|
|
122
|
+
const { asset, share } = this;
|
|
123
|
+
switch (decoded.functionName) {
|
|
124
|
+
case "deposit": return {
|
|
125
|
+
tokenIn: asset,
|
|
126
|
+
tokenOut: share,
|
|
127
|
+
amountIn: decoded.args[0]
|
|
128
|
+
};
|
|
129
|
+
case "depositDiff": {
|
|
130
|
+
const [leftoverAmount] = decoded.args;
|
|
131
|
+
const running = balances.getOrZero(asset);
|
|
132
|
+
return {
|
|
133
|
+
tokenIn: asset,
|
|
134
|
+
tokenOut: share,
|
|
135
|
+
amountIn: running > leftoverAmount ? running - leftoverAmount : 0n
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
case "redeem": return {
|
|
139
|
+
tokenIn: share,
|
|
140
|
+
tokenOut: asset,
|
|
141
|
+
amountIn: decoded.args[0]
|
|
142
|
+
};
|
|
143
|
+
case "redeemDiff": {
|
|
144
|
+
const [leftoverAmount] = decoded.args;
|
|
145
|
+
const running = balances.getOrZero(share);
|
|
146
|
+
return {
|
|
147
|
+
tokenIn: share,
|
|
148
|
+
tokenOut: asset,
|
|
149
|
+
amountIn: running > leftoverAmount ? running - leftoverAmount : 0n
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
default: return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
101
155
|
async applyBalanceChanges(balances, decoded) {
|
|
102
156
|
switch (decoded.functionName) {
|
|
103
157
|
case "depositDiff": {
|
|
@@ -10,6 +10,10 @@ let viem = require("viem");
|
|
|
10
10
|
//#region src/onchain/market/adapters/contracts/MidasGatewayAdapterContract.ts
|
|
11
11
|
const abi = require_onchain_market_adapters_abi_adapters_iMidasGatewayAdapterV311.iMidasGatewayAdapterV311Abi;
|
|
12
12
|
const protocolAbi = require_onchain_market_adapters_abi_midas_iMidasGatewayV311.iMidasGatewayV311Abi;
|
|
13
|
+
const receiveGreenlistCalldata = (0, viem.encodeFunctionData)({
|
|
14
|
+
abi,
|
|
15
|
+
functionName: "receiveGreenlist"
|
|
16
|
+
});
|
|
13
17
|
var MidasGatewayAdapterContract = class extends require_onchain_market_adapters_contracts_AbstractAdapter.AbstractAdapterContract {
|
|
14
18
|
#version;
|
|
15
19
|
#gateway;
|
|
@@ -165,6 +169,15 @@ var MidasGatewayAdapterContract = class extends require_onchain_market_adapters_
|
|
|
165
169
|
const [redeemer] = decoded.args;
|
|
166
170
|
return { redeemer };
|
|
167
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* `receiveGreenlist()` is prepended by `prependMidasReceiveGreenlist`
|
|
174
|
+
* before the balance bracket when the multicall mints a permissioned
|
|
175
|
+
* mToken: it only greenlists the credit account and is balance-neutral,
|
|
176
|
+
* so it is legal outside a bracket and leaves balances untouched.
|
|
177
|
+
*/
|
|
178
|
+
replayOutOfBracketCall(_balances, calldata) {
|
|
179
|
+
return calldata === receiveGreenlistCalldata;
|
|
180
|
+
}
|
|
168
181
|
async applyBalanceChanges(balances, decoded) {
|
|
169
182
|
switch (decoded.functionName) {
|
|
170
183
|
case "depositInstantDiff": {
|
|
@@ -64,12 +64,9 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
|
|
|
64
64
|
**/
|
|
65
65
|
async listStrategyPositions(props) {
|
|
66
66
|
const { owner, includeZeroDebt, blockNumber } = props;
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
});
|
|
71
|
-
const withdrawals = await Promise.all(describable.map((ca) => this.#accountWithdrawals(ca, blockNumber)));
|
|
72
|
-
return describable.map((ca, i) => this.#toStrategyPosition(ca, withdrawals[i] ?? new require_onchain_utils_AddressMap.AddressMap()));
|
|
67
|
+
const accounts = await this.sdk.accounts.getBorrowerCreditAccounts(owner, { includeZeroDebt }, blockNumber);
|
|
68
|
+
const withdrawals = await Promise.all(accounts.map((ca) => this.#accountWithdrawals(ca, blockNumber)));
|
|
69
|
+
return accounts.map((ca, i) => this.#toStrategyPosition(ca, withdrawals[i] ?? new require_onchain_utils_AddressMap.AddressMap()));
|
|
73
70
|
}
|
|
74
71
|
/**
|
|
75
72
|
* Health factor of an account state, in basis points (`10000` = 1.0).
|
|
@@ -180,14 +177,11 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
|
|
|
180
177
|
const token = market.underlyingToken;
|
|
181
178
|
const totalDebtValue = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
182
179
|
const target = require_onchain_chain_chains.getAccountTargetCollateral(ca.creditAccount, this.sdk.chainId) ?? suite.strategyTargetCollateral;
|
|
183
|
-
const
|
|
184
|
-
const
|
|
185
|
-
const timeToLiquidation = this.timeToLiquidation(snapshot);
|
|
186
|
-
const liquidationPrice = this.liquidationPrice(snapshot);
|
|
187
|
-
const zeroDebt = ca.debt === 0n;
|
|
180
|
+
const priceFailed = !ca.success;
|
|
181
|
+
const recomputeTotals = ca.debt === 0n || priceFailed;
|
|
188
182
|
const collaterals = [];
|
|
189
|
-
let totalValue =
|
|
190
|
-
let totalValueUSD =
|
|
183
|
+
let totalValue = recomputeTotals ? 0n : ca.totalValue;
|
|
184
|
+
let totalValueUSD = recomputeTotals ? 0n : ca.totalValueUSD;
|
|
191
185
|
for (const t of ca.tokens) {
|
|
192
186
|
if (t.balance <= 10n) continue;
|
|
193
187
|
collaterals.push({
|
|
@@ -195,13 +189,21 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
|
|
|
195
189
|
quota: priceOracle.toTokenAmount(market.underlying, t.quota),
|
|
196
190
|
withdrawals: withdrawals.get(t.token) ?? []
|
|
197
191
|
});
|
|
198
|
-
if (
|
|
192
|
+
if (recomputeTotals) {
|
|
199
193
|
const value = priceOracle.safeConvert(t.token, market.underlying, t.balance) || 0n;
|
|
200
194
|
totalValue += value;
|
|
201
195
|
const usd = priceOracle.safeConvertToUSD(t.token, t.balance) || 0n;
|
|
202
196
|
totalValueUSD += usd;
|
|
203
197
|
}
|
|
204
198
|
}
|
|
199
|
+
const snapshot = {
|
|
200
|
+
...require_onchain_positions_types.accountSnapshotFromCreditAccountData(ca),
|
|
201
|
+
totalValue
|
|
202
|
+
};
|
|
203
|
+
const borrowRate = this.borrowRate(snapshot);
|
|
204
|
+
const timeToLiquidation = this.timeToLiquidation(snapshot);
|
|
205
|
+
const liquidationPrice = this.liquidationPrice(snapshot);
|
|
206
|
+
const totalDebtUSD = priceFailed ? priceOracle.safeConvertToUSD(market.underlying, totalDebtValue) ?? 0n : ca.totalDebtUSD;
|
|
205
207
|
return {
|
|
206
208
|
kind: "strategy",
|
|
207
209
|
chainId: this.sdk.chainId,
|
|
@@ -215,18 +217,19 @@ var PositionsService = class extends require_onchain_base_SDKConstruct.SDKConstr
|
|
|
215
217
|
totalDebt: {
|
|
216
218
|
token,
|
|
217
219
|
value: totalDebtValue,
|
|
218
|
-
valueUsd: require_onchain_market_math.usdToNumber(
|
|
220
|
+
valueUsd: require_onchain_market_math.usdToNumber(totalDebtUSD)
|
|
219
221
|
},
|
|
220
222
|
totalValue: {
|
|
221
223
|
token,
|
|
222
224
|
value: totalValue,
|
|
223
225
|
valueUsd: require_onchain_market_math.usdToNumber(totalValueUSD)
|
|
224
226
|
},
|
|
225
|
-
healthFactor: require_onchain_market_math.healthFactorBps(ca.healthFactor),
|
|
227
|
+
healthFactor: priceFailed ? this.healthFactor(snapshot) : require_onchain_market_math.healthFactorBps(ca.healthFactor),
|
|
226
228
|
borrowRate,
|
|
227
229
|
timeToLiquidation,
|
|
228
230
|
liquidationPrice,
|
|
229
|
-
collaterals
|
|
231
|
+
collaterals,
|
|
232
|
+
...priceFailed ? { error: require_model_positions.STRATEGY_POSITION_COLLATERAL_ERROR } : {}
|
|
230
233
|
};
|
|
231
234
|
}
|
|
232
235
|
/**
|
|
@@ -2,11 +2,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_onchain_utils_AssetsMap = require("../../onchain/utils/AssetsMap.js");
|
|
3
3
|
require("../../onchain/constants/math.js");
|
|
4
4
|
const require_onchain_market_adapters_contracts_AbstractAdapter = require("../../onchain/market/adapters/contracts/AbstractAdapter.js");
|
|
5
|
-
const require_onchain_market_adapters_contracts_ERC4626AdapterContract = require("../../onchain/market/adapters/contracts/ERC4626AdapterContract.js");
|
|
6
5
|
const require_model_previews = require("../../model/previews.js");
|
|
7
6
|
require("../../model/index.js");
|
|
8
7
|
require("../../onchain/index.js");
|
|
9
|
-
const require_preview_preview_applyRWAWrapUnwrap = require("./applyRWAWrapUnwrap.js");
|
|
10
8
|
//#region src/preview/preview/replayInnerOperations.ts
|
|
11
9
|
/**
|
|
12
10
|
* Creates a {@link ReplayState} around the given account seed, with empty
|
|
@@ -94,26 +92,25 @@ function applyWithdrawCollateral(state, op) {
|
|
|
94
92
|
*
|
|
95
93
|
* Inside a bracket, the adapter's balance changes are previewed via
|
|
96
94
|
* {@link AbstractAdapterContract.previewBalanceChanges}. Outside a bracket,
|
|
97
|
-
* only
|
|
98
|
-
* nothing enforces the outcome of any other out-of-bracket
|
|
99
|
-
* on-chain, so its effect on balances cannot be previewed.
|
|
95
|
+
* only calls that {@link AbstractAdapterContract.replayOutOfBracketCall}
|
|
96
|
+
* accepts are allowed; nothing enforces the outcome of any other out-of-bracket
|
|
97
|
+
* adapter call on-chain, so its effect on balances cannot be previewed.
|
|
100
98
|
*/
|
|
101
99
|
async function applyExecute(sdk, op, inBracket, balances) {
|
|
102
100
|
const adapter = sdk.getContract(op.adapter);
|
|
103
101
|
if (!inBracket) {
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
message: `call to ${op.adapter} outside of a storeExpectedBalances/compareBalances bracket`
|
|
107
|
-
};
|
|
108
|
-
try {
|
|
109
|
-
require_preview_preview_applyRWAWrapUnwrap.applyRWAWrapUnwrap(adapter, op.calldata, balances);
|
|
110
|
-
return;
|
|
102
|
+
if (adapter instanceof require_onchain_market_adapters_contracts_AbstractAdapter.AbstractAdapterContract) try {
|
|
103
|
+
if (adapter.replayOutOfBracketCall(balances, op.calldata)) return;
|
|
111
104
|
} catch (e) {
|
|
112
105
|
return {
|
|
113
|
-
code: require_model_previews.
|
|
106
|
+
code: require_model_previews.ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL,
|
|
114
107
|
message: e instanceof Error ? e.message : String(e)
|
|
115
108
|
};
|
|
116
109
|
}
|
|
110
|
+
return {
|
|
111
|
+
code: require_model_previews.ERROR_ADAPTER_CALL_OUTSIDE_BRACKET,
|
|
112
|
+
message: `call to ${op.adapter} outside of a storeExpectedBalances/compareBalances bracket`
|
|
113
|
+
};
|
|
117
114
|
}
|
|
118
115
|
if (!(adapter instanceof require_onchain_market_adapters_contracts_AbstractAdapter.AbstractAdapterContract)) return {
|
|
119
116
|
code: require_model_previews.ERROR_NON_ADAPTER_CALL_IN_BRACKET,
|
|
@@ -129,18 +126,6 @@ async function applyExecute(sdk, op, inBracket, balances) {
|
|
|
129
126
|
};
|
|
130
127
|
}
|
|
131
128
|
}
|
|
132
|
-
/**
|
|
133
|
-
* True when the ERC4626 adapter converts an RWA underlying, i.e. it is the
|
|
134
|
-
* wrap/unwrap adapter of an RWA market rather than a regular vault strategy
|
|
135
|
-
* adapter.
|
|
136
|
-
*/
|
|
137
|
-
function isRWAShare(sdk, adapter) {
|
|
138
|
-
if (adapter instanceof require_onchain_market_adapters_contracts_ERC4626AdapterContract.ERC4626AdapterContract) {
|
|
139
|
-
const meta = sdk.tokensMeta.get(adapter.share);
|
|
140
|
-
return !!meta && sdk.tokensMeta.isRWAUnderlying(meta);
|
|
141
|
-
}
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
129
|
//#endregion
|
|
145
130
|
exports.makeReplayState = makeReplayState;
|
|
146
131
|
exports.replayInnerOperations = replayInnerOperations;
|
|
@@ -14,8 +14,9 @@ const tagDiff = makeTagDiff({
|
|
|
14
14
|
* Matches two position listings per wallet by {@link positionId} and reports
|
|
15
15
|
* every field the two sources disagree on.
|
|
16
16
|
*
|
|
17
|
-
* Nothing is filtered out. A field only one mode can fill,
|
|
18
|
-
*
|
|
17
|
+
* Nothing is filtered out. A field only one mode can fill, a strategy field
|
|
18
|
+
* both-mode merge overlays from the backend, or a USD value that drifted
|
|
19
|
+
* within snapshot-lag noise, is still reported — tagged
|
|
19
20
|
* {@link FieldDiff.expected} so that {@link CompareCounts.clean} can ignore it
|
|
20
21
|
* while {@link CompareCounts.identical} stays strict.
|
|
21
22
|
**/
|
|
@@ -24,15 +24,26 @@ function makeTagDiff(rulesByKind) {
|
|
|
24
24
|
if (!rules) return diff;
|
|
25
25
|
const path = collapseArrayKeys(diff.path);
|
|
26
26
|
if (isModeScoped(path, rules)) return withExpected(diff, "mode-scoped");
|
|
27
|
+
if (isBackendPreferred(path, rules)) return withExpected(diff, "backend-preferred");
|
|
27
28
|
const tag = rules.get(path);
|
|
28
29
|
if (tag && typeof tag === "object" && withinTolerance(tag.tolerance, diff)) return withExpected(diff, "tolerance");
|
|
29
30
|
return diff;
|
|
30
31
|
};
|
|
31
32
|
}
|
|
33
|
+
function pathMatchesRule(path, rulePath) {
|
|
34
|
+
return path === rulePath || path.startsWith(`${rulePath}.`) || path.startsWith(`${rulePath}[`);
|
|
35
|
+
}
|
|
32
36
|
function isModeScoped(path, rules) {
|
|
33
37
|
for (const [rulePath, tag] of rules) {
|
|
34
38
|
if (tag !== "offchainOnly" && tag !== "onchainOnly") continue;
|
|
35
|
-
if (path
|
|
39
|
+
if (pathMatchesRule(path, rulePath)) return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
function isBackendPreferred(path, rules) {
|
|
44
|
+
for (const [rulePath, tag] of rules) {
|
|
45
|
+
if (tag !== "backendPreferred") continue;
|
|
46
|
+
if (pathMatchesRule(path, rulePath)) return true;
|
|
36
47
|
}
|
|
37
48
|
return false;
|
|
38
49
|
}
|
|
@@ -107,7 +107,7 @@ function printCompareSummary(noun, report, extraLines = []) {
|
|
|
107
107
|
})));
|
|
108
108
|
}
|
|
109
109
|
if (expected.length) {
|
|
110
|
-
console.log("\nexpected fields (mode-scoped or within tolerance):");
|
|
110
|
+
console.log("\nexpected fields (mode-scoped, backend-preferred, or within tolerance):");
|
|
111
111
|
console.table(expected.slice(0, 25).map((entry) => ({
|
|
112
112
|
field: entry.path,
|
|
113
113
|
rows: entry.expected,
|
|
@@ -12,6 +12,13 @@ function onchainOnly(schema) {
|
|
|
12
12
|
return schema.meta({ compare: "onchainOnly" });
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
+
* Marks a field whose backend value both-mode merge overlays onto the chain
|
|
16
|
+
* row, so a source disagreement is expected.
|
|
17
|
+
**/
|
|
18
|
+
function backendPreferred(schema) {
|
|
19
|
+
return schema.meta({ compare: "backendPreferred" });
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
15
22
|
* Marks a numeric field whose two sources may drift within {@link kind}.
|
|
16
23
|
**/
|
|
17
24
|
function tolerance(schema, kind) {
|
|
@@ -26,4 +33,4 @@ function compareTagOf(schema) {
|
|
|
26
33
|
return meta.compare;
|
|
27
34
|
}
|
|
28
35
|
//#endregion
|
|
29
|
-
export { compareTagOf, offchainOnly, onchainOnly, tolerance };
|
|
36
|
+
export { backendPreferred, compareTagOf, offchainOnly, onchainOnly, tolerance };
|
package/dist/esm/model/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS } from "./charts.js";
|
|
2
|
-
import { compareTagOf, offchainOnly, onchainOnly, tolerance } from "./compare.schema.js";
|
|
2
|
+
import { backendPreferred, compareTagOf, offchainOnly, onchainOnly, tolerance } from "./compare.schema.js";
|
|
3
3
|
import { amountSchema, assetTypeSchema, bpsSchema, chainIdSchema, leverageSchema, timestampSchema, tokenAmountSchema, tokenSchema, txCallSchema, underlyingTokenSchema } from "./primitives.schema.js";
|
|
4
4
|
import { chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, poolOpportunityChartMetricSchema, poolPositionChartMetricSchema, strategyOpportunityChartMetricSchema, strategyPositionChartMetricSchema } from "./charts.schema.js";
|
|
5
5
|
import "./curators.js";
|
|
@@ -13,10 +13,10 @@ import "./notices.js";
|
|
|
13
13
|
import { noticeKindSchema, noticeSchema } from "./notices.schema.js";
|
|
14
14
|
import { matchesOpportunityFilter, opportunityId, poolOpportunityId, strategyOpportunityId } from "./opportunities.js";
|
|
15
15
|
import { apyBreakdownSchema, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityKeySchema, opportunityKindSchema, opportunitySchema, pointRewardsSchema, pointsProgramSchema, poolOpportunityDetailSchema, poolOpportunityKeySchema, poolOpportunitySchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, rewardsSchema, strategyOpportunityDetailSchema, strategyOpportunityKeySchema, strategyOpportunitySchema, tokenRewardsSchema } from "./opportunities.schema.js";
|
|
16
|
-
import { liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId } from "./positions.js";
|
|
16
|
+
import { STRATEGY_POSITION_COLLATERAL_ERROR, liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId } from "./positions.js";
|
|
17
17
|
import { borrowRateBreakdownSchema, pnlBreakdownSchema, pointsProgramPnLSchema, pointsRewardsPnLSchema, poolPositionKeySchema, poolPositionSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionKeySchema, positionKindSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionsTotalsSchema, rewardsPnLSchema, strategyPositionKeySchema, strategyPositionSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema } from "./positions.schema.js";
|
|
18
|
-
import { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL,
|
|
18
|
+
import { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL } from "./previews.js";
|
|
19
19
|
import "./primitives.js";
|
|
20
20
|
import "./response.js";
|
|
21
21
|
import { chainFailedSchema, chainMetadataSchema, chainSucceededSchema, dataSourceSchema, responseMetadataSchema, responseSchema } from "./response.schema.js";
|
|
22
|
-
export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL,
|
|
22
|
+
export { CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL, FILTER_ALL, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, amountSchema, apyBreakdownSchema, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, curatorNameSchema, curatorSchema, dataSourceSchema, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, instantReceivedAssetSchema, isFilterSet, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, quotaAssetSchema, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema };
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { isFilterSet } from "./filters.js";
|
|
2
2
|
//#region src/model/positions.ts
|
|
3
3
|
/**
|
|
4
|
+
* Set on {@link StrategyPosition.error} when the account could not be fully
|
|
5
|
+
* valued (e.g. a dead price feed).
|
|
6
|
+
**/
|
|
7
|
+
const STRATEGY_POSITION_COLLATERAL_ERROR = "collateral computation failed";
|
|
8
|
+
/**
|
|
4
9
|
* Builds the canonical id of a pool position.
|
|
5
10
|
*
|
|
6
11
|
* @example
|
|
@@ -84,4 +89,4 @@ function positionUnderlying(position) {
|
|
|
84
89
|
}
|
|
85
90
|
}
|
|
86
91
|
//#endregion
|
|
87
|
-
export { liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId };
|
|
92
|
+
export { STRATEGY_POSITION_COLLATERAL_ERROR, liquidationPositionId, matchesPositionFilter, poolPositionId, positionId, strategyPositionId };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ZodAddress, ZodBigInt, ZodHex } from "../onchain/utils/zod.js";
|
|
2
|
-
import { offchainOnly, onchainOnly, tolerance } from "./compare.schema.js";
|
|
2
|
+
import { backendPreferred, offchainOnly, onchainOnly, tolerance } from "./compare.schema.js";
|
|
3
3
|
import { assetTypeSchema, bpsSchema, chainIdSchema, leverageSchema, timestampSchema, tokenAmountSchema, tokenSchema, underlyingTokenSchema } from "./primitives.schema.js";
|
|
4
4
|
import { isFilterSet } from "./filters.js";
|
|
5
5
|
import { booleanParamSchema, encodeFlag, filterable } from "./filters.schema.js";
|
|
@@ -95,12 +95,12 @@ const borrowRateBreakdownSchema = z.object({
|
|
|
95
95
|
**/
|
|
96
96
|
const strategyPositionSchema = z.object({
|
|
97
97
|
kind: z.literal("strategy"),
|
|
98
|
-
name: z.string(),
|
|
98
|
+
name: backendPreferred(z.string()),
|
|
99
99
|
chainId: chainIdSchema,
|
|
100
100
|
creditManager: ZodAddress(),
|
|
101
101
|
creditAccount: ZodAddress(),
|
|
102
102
|
underlyingToken: underlyingTokenSchema,
|
|
103
|
-
targetCollateral: tokenSchema.nullable(),
|
|
103
|
+
targetCollateral: backendPreferred(tokenSchema.nullable()),
|
|
104
104
|
leverage: tolerance(leverageSchema, "float"),
|
|
105
105
|
borrowApy: tolerance(bpsSchema, "bps"),
|
|
106
106
|
borrowApyAvg7D: offchainOnly(bpsSchema).optional(),
|
|
@@ -114,7 +114,8 @@ const strategyPositionSchema = z.object({
|
|
|
114
114
|
timeToLiquidation: onchainOnly(ZodBigInt().nullable()).optional(),
|
|
115
115
|
liquidationPrice: onchainOnly(ZodBigInt().nullable()).optional(),
|
|
116
116
|
pnl: offchainOnly(pnlBreakdownSchema).optional(),
|
|
117
|
-
collaterals: z.array(positionCollateralSchema)
|
|
117
|
+
collaterals: z.array(positionCollateralSchema),
|
|
118
|
+
error: z.string().optional()
|
|
118
119
|
});
|
|
119
120
|
/**
|
|
120
121
|
* {@link Position}
|
|
@@ -20,9 +20,10 @@ const ERROR_NON_ADAPTER_CALL_IN_BRACKET = 1003;
|
|
|
20
20
|
**/
|
|
21
21
|
const ERROR_UNPREVIEWABLE_ADAPTER_CALL = 1004;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* An out-of-bracket adapter call that is allowed there (e.g. RWA wrap/unwrap)
|
|
24
|
+
* could not be decoded or replayed
|
|
24
25
|
**/
|
|
25
|
-
const
|
|
26
|
+
const ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL = 1005;
|
|
26
27
|
/**
|
|
27
28
|
* `msg.value` does not fit into the declared WETH collateral
|
|
28
29
|
* Transactions can have arbitrary value, but the ones that we create
|
|
@@ -32,4 +33,4 @@ const ERROR_INVALID_TRANSACTION_VALUE = 1006;
|
|
|
32
33
|
/** A token in the preview could not be priced by the oracle */
|
|
33
34
|
const ERROR_UNPRICEABLE_TOKEN = 2001;
|
|
34
35
|
//#endregion
|
|
35
|
-
export { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL,
|
|
36
|
+
export { ERROR_ADAPTER_CALL_OUTSIDE_BRACKET, ERROR_INVALID_TRANSACTION_VALUE, ERROR_MALFORMED_BRACKET, ERROR_NON_ADAPTER_CALL_IN_BRACKET, ERROR_UNPREVIEWABLE_ADAPTER_CALL, ERROR_UNPRICEABLE_TOKEN, ERROR_UNSUPPORTED_OUT_OF_BRACKET_CALL };
|
|
@@ -114,6 +114,20 @@ var AbstractAdapterContract = class extends BaseContract {
|
|
|
114
114
|
await this.applyBalanceChanges(balances, decoded);
|
|
115
115
|
}
|
|
116
116
|
/**
|
|
117
|
+
* Replays this adapter call when it appears outside a
|
|
118
|
+
* storeExpectedBalances/compareBalances bracket, mutating `balances` in
|
|
119
|
+
* place, and returns `true` when the call is legal there.
|
|
120
|
+
*
|
|
121
|
+
* Base implementation returns `false`: nothing enforces the outcome of an
|
|
122
|
+
* out-of-bracket adapter call on-chain, so it cannot be previewed.
|
|
123
|
+
*
|
|
124
|
+
* @throws when the call is allowed outside a bracket but its calldata
|
|
125
|
+
* cannot be decoded
|
|
126
|
+
*/
|
|
127
|
+
replayOutOfBracketCall(_balances, _calldata) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
117
131
|
* Applies the balance changes of a decoded adapter call to the running
|
|
118
132
|
* balances, mutating them in place. Overrides should express changes via
|
|
119
133
|
* {@link setLeftover} (diff-style calls) and {@link spendExact}
|