@gearbox-protocol/sdk 16.0.0-next.22 → 16.0.0-next.23
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/onchain/accounts/intents/maxWithdrawCollateral.js +2 -2
- package/dist/cjs/onchain/accounts/intents/open-strategy.js +7 -4
- package/dist/cjs/onchain/accounts/intents/realize.js +10 -6
- package/dist/cjs/onchain/accounts/intents/tail.js +3 -2
- package/dist/cjs/onchain/accounts/intents/testing/market.js +1 -1
- package/dist/cjs/onchain/accounts/intents/testing/sdk-mock.js +18 -1
- package/dist/cjs/onchain/accounts/intents/tests/add-collateral.fixtures.js +4 -4
- package/dist/cjs/onchain/accounts/intents/tests/adjust-leverage.fixtures.js +15 -15
- package/dist/cjs/onchain/accounts/intents/tests/deposit.fixtures.js +13 -13
- package/dist/cjs/onchain/accounts/intents/tests/finish-decrease-leverage.fixtures.js +2 -2
- package/dist/cjs/onchain/accounts/intents/tests/finish-withdraw.fixtures.js +2 -2
- package/dist/cjs/onchain/accounts/intents/tests/withdraw-asset.fixtures.js +4 -4
- package/dist/cjs/onchain/accounts/intents/tests/withdraw.fixtures.js +7 -7
- package/dist/cjs/onchain/accounts/intents/utils/adjust-state-to-snapshot.js +8 -5
- package/dist/cjs/onchain/accounts/intents/utils/common.js +2 -2
- package/dist/cjs/onchain/accounts/intents/utils/credit-account-slice.js +4 -4
- package/dist/cjs/onchain/accounts/intents/view.js +2 -2
- package/dist/cjs/onchain/market/MarketSuite.js +15 -0
- package/dist/cjs/onchain/market/math.js +6 -2
- package/dist/cjs/onchain/pools/PoolService.js +25 -29
- package/dist/cjs/preview/index.js +3 -1
- package/dist/cjs/preview/preview/buildDelayedPreview.js +4 -4
- package/dist/cjs/preview/preview/previewAdjustCreditAccount.js +3 -3
- package/dist/cjs/preview/preview/previewCloseOrRepayCreditAccount.js +1 -1
- package/dist/cjs/preview/preview/previewOpenCreditAccount.js +7 -7
- package/dist/cjs/preview/validate/checkOperation.js +47 -37
- package/dist/cjs/preview/validate/checkSimulation.js +3 -16
- package/dist/cjs/preview/validate/index.js +3 -1
- package/dist/cjs/sdk/execute/ExecuteApi.js +9 -6
- package/dist/cjs/sdk/prepare/PrepareApi.js +4 -1
- package/dist/esm/onchain/accounts/intents/maxWithdrawCollateral.js +2 -2
- package/dist/esm/onchain/accounts/intents/open-strategy.js +7 -4
- package/dist/esm/onchain/accounts/intents/realize.js +10 -6
- package/dist/esm/onchain/accounts/intents/tail.js +3 -2
- package/dist/esm/onchain/accounts/intents/testing/market.js +1 -1
- package/dist/esm/onchain/accounts/intents/testing/sdk-mock.js +18 -1
- package/dist/esm/onchain/accounts/intents/tests/add-collateral.fixtures.js +4 -4
- package/dist/esm/onchain/accounts/intents/tests/adjust-leverage.fixtures.js +15 -15
- package/dist/esm/onchain/accounts/intents/tests/deposit.fixtures.js +13 -13
- package/dist/esm/onchain/accounts/intents/tests/finish-decrease-leverage.fixtures.js +2 -2
- package/dist/esm/onchain/accounts/intents/tests/finish-withdraw.fixtures.js +2 -2
- package/dist/esm/onchain/accounts/intents/tests/withdraw-asset.fixtures.js +4 -4
- package/dist/esm/onchain/accounts/intents/tests/withdraw.fixtures.js +7 -7
- package/dist/esm/onchain/accounts/intents/utils/adjust-state-to-snapshot.js +8 -5
- package/dist/esm/onchain/accounts/intents/utils/common.js +2 -2
- package/dist/esm/onchain/accounts/intents/utils/credit-account-slice.js +4 -4
- package/dist/esm/onchain/accounts/intents/view.js +2 -2
- package/dist/esm/onchain/market/MarketSuite.js +15 -0
- package/dist/esm/onchain/market/math.js +6 -2
- package/dist/esm/onchain/pools/PoolService.js +25 -29
- package/dist/esm/preview/index.js +2 -2
- package/dist/esm/preview/preview/buildDelayedPreview.js +4 -4
- package/dist/esm/preview/preview/previewAdjustCreditAccount.js +3 -3
- package/dist/esm/preview/preview/previewCloseOrRepayCreditAccount.js +1 -1
- package/dist/esm/preview/preview/previewOpenCreditAccount.js +7 -7
- package/dist/esm/preview/validate/checkOperation.js +45 -37
- package/dist/esm/preview/validate/checkSimulation.js +5 -18
- package/dist/esm/preview/validate/index.js +2 -2
- package/dist/esm/sdk/execute/ExecuteApi.js +9 -6
- package/dist/esm/sdk/prepare/PrepareApi.js +4 -1
- package/dist/types/model/index.d.ts +2 -2
- package/dist/types/model/previews.d.ts +59 -109
- package/dist/types/onchain/accounts/intents/open-strategy.d.ts +15 -29
- package/dist/types/onchain/accounts/intents/testing/expect.d.ts +6 -2
- package/dist/types/onchain/accounts/intents/testing/market.d.ts +1 -1
- package/dist/types/onchain/accounts/intents/testing/sdk-mock.d.ts +1 -1
- package/dist/types/onchain/accounts/intents/tests/add-collateral.fixtures.d.ts +1 -1
- package/dist/types/onchain/accounts/intents/tests/adjust-leverage.fixtures.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/tests/deposit.fixtures.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/tests/withdraw-asset.fixtures.d.ts +1 -1
- package/dist/types/onchain/accounts/intents/tests/withdraw.fixtures.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/types.d.ts +8 -59
- package/dist/types/onchain/accounts/intents/utils/adjust-state-to-snapshot.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/utils/credit-account-slice.d.ts +3 -3
- package/dist/types/onchain/market/MarketSuite.d.ts +13 -1
- package/dist/types/onchain/market/math.d.ts +5 -1
- package/dist/types/onchain/pools/types.d.ts +6 -4
- package/dist/types/preview/index.d.ts +2 -2
- package/dist/types/preview/preview/buildDelayedPreview.d.ts +1 -1
- package/dist/types/preview/validate/checkOperation.d.ts +24 -7
- package/dist/types/preview/validate/index.d.ts +2 -2
- package/package.json +1 -1
|
@@ -21,6 +21,14 @@ require("../market/index.js");
|
|
|
21
21
|
*/
|
|
22
22
|
const LIQUIDITY_SAFETY_NUM = 99999n;
|
|
23
23
|
const LIQUIDITY_SAFETY_DENOM = 100000n;
|
|
24
|
+
/**
|
|
25
|
+
* What the pool can actually pay out right now, shaved by a hair so a
|
|
26
|
+
* withdrawal sized against it does not fail on rounding.
|
|
27
|
+
**/
|
|
28
|
+
function payoutCeiling(market) {
|
|
29
|
+
const { pool } = market;
|
|
30
|
+
return market.priceOracle.toAmount(pool.underlying, pool.pool.availableLiquidity * LIQUIDITY_SAFETY_NUM / LIQUIDITY_SAFETY_DENOM);
|
|
31
|
+
}
|
|
24
32
|
var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
|
|
25
33
|
/**
|
|
26
34
|
* {@inheritDoc IPoolsService.getDepositTokensIn}
|
|
@@ -126,7 +134,9 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
|
|
|
126
134
|
*/
|
|
127
135
|
simulateDeposit(props) {
|
|
128
136
|
const { pool: poolAddr, amount } = props;
|
|
129
|
-
const
|
|
137
|
+
const market = this.sdk.marketRegister.findByPool(poolAddr);
|
|
138
|
+
const { pool } = market;
|
|
139
|
+
const { toTokenAmount } = market.priceOracle;
|
|
130
140
|
const tokenIn = props.tokenIn ?? pool.underlying;
|
|
131
141
|
const tokenOut = this.#resolveTokenOut(props.tokenOut, () => this.getDepositTokensOut(poolAddr, tokenIn), {
|
|
132
142
|
poolAddr,
|
|
@@ -135,14 +145,8 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
|
|
|
135
145
|
});
|
|
136
146
|
const { zapper } = this.getDepositMetadata(poolAddr, tokenIn, tokenOut);
|
|
137
147
|
return {
|
|
138
|
-
tokenIn:
|
|
139
|
-
|
|
140
|
-
balance: amount
|
|
141
|
-
},
|
|
142
|
-
tokenOut: {
|
|
143
|
-
token: tokenOut,
|
|
144
|
-
balance: toShares(pool.pool, amount)
|
|
145
|
-
},
|
|
148
|
+
tokenIn: toTokenAmount(tokenIn, amount),
|
|
149
|
+
tokenOut: toTokenAmount(tokenOut, toShares(pool.pool, amount)),
|
|
146
150
|
zapper: zapper?.baseParams.addr
|
|
147
151
|
};
|
|
148
152
|
}
|
|
@@ -151,7 +155,9 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
|
|
|
151
155
|
*/
|
|
152
156
|
simulateWithdraw(props) {
|
|
153
157
|
const { pool: poolAddr, amount } = props;
|
|
154
|
-
const
|
|
158
|
+
const market = this.sdk.marketRegister.findByPool(poolAddr);
|
|
159
|
+
const { pool } = market;
|
|
160
|
+
const { toTokenAmount } = market.priceOracle;
|
|
155
161
|
const tokenIn = props.tokenIn ?? poolAddr;
|
|
156
162
|
const tokenOut = this.#resolveTokenOut(props.tokenOut, () => this.getWithdrawalTokensOut(poolAddr, tokenIn), {
|
|
157
163
|
poolAddr,
|
|
@@ -160,16 +166,10 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
|
|
|
160
166
|
});
|
|
161
167
|
const { zapper } = this.getWithdrawalMetadata(poolAddr, tokenIn, tokenOut);
|
|
162
168
|
return {
|
|
163
|
-
tokenIn:
|
|
164
|
-
|
|
165
|
-
balance: toSharesUp(pool.pool, amount)
|
|
166
|
-
},
|
|
167
|
-
tokenOut: {
|
|
168
|
-
token: tokenOut,
|
|
169
|
-
balance: amount
|
|
170
|
-
},
|
|
169
|
+
tokenIn: toTokenAmount(tokenIn, toSharesUp(pool.pool, amount)),
|
|
170
|
+
tokenOut: toTokenAmount(tokenOut, amount),
|
|
171
171
|
zapper: zapper?.baseParams.addr,
|
|
172
|
-
availableLiquidity:
|
|
172
|
+
availableLiquidity: payoutCeiling(market)
|
|
173
173
|
};
|
|
174
174
|
}
|
|
175
175
|
/**
|
|
@@ -177,7 +177,9 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
|
|
|
177
177
|
*/
|
|
178
178
|
simulateRedeem(props) {
|
|
179
179
|
const { pool: poolAddr, amount } = props;
|
|
180
|
-
const
|
|
180
|
+
const market = this.sdk.marketRegister.findByPool(poolAddr);
|
|
181
|
+
const { pool } = market;
|
|
182
|
+
const { toTokenAmount } = market.priceOracle;
|
|
181
183
|
const tokenIn = props.tokenIn ?? poolAddr;
|
|
182
184
|
const tokenOut = this.#resolveTokenOut(props.tokenOut, () => this.getWithdrawalTokensOut(poolAddr, tokenIn), {
|
|
183
185
|
poolAddr,
|
|
@@ -186,16 +188,10 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
|
|
|
186
188
|
});
|
|
187
189
|
const { zapper } = this.getWithdrawalMetadata(poolAddr, tokenIn, tokenOut);
|
|
188
190
|
return {
|
|
189
|
-
tokenIn:
|
|
190
|
-
|
|
191
|
-
balance: amount
|
|
192
|
-
},
|
|
193
|
-
tokenOut: {
|
|
194
|
-
token: tokenOut,
|
|
195
|
-
balance: toAssets(pool.pool, amount)
|
|
196
|
-
},
|
|
191
|
+
tokenIn: toTokenAmount(tokenIn, amount),
|
|
192
|
+
tokenOut: toTokenAmount(tokenOut, toAssets(pool.pool, amount)),
|
|
197
193
|
zapper: zapper?.baseParams.addr,
|
|
198
|
-
availableLiquidity:
|
|
194
|
+
availableLiquidity: payoutCeiling(market)
|
|
199
195
|
};
|
|
200
196
|
}
|
|
201
197
|
/**
|
|
@@ -57,7 +57,7 @@ exports.checkPrerequisites = require_preview_prerequisites_checkPrerequisites.ch
|
|
|
57
57
|
exports.checkSimulation = require_preview_validate_checkSimulation.checkSimulation;
|
|
58
58
|
exports.classifyCloseOrRepay = require_preview_preview_detectCloseOrRepay.classifyCloseOrRepay;
|
|
59
59
|
exports.classifyInnerOperations = require_preview_parse_classifyInnerOperations.classifyInnerOperations;
|
|
60
|
-
exports.
|
|
60
|
+
exports.collateralIssue = require_preview_validate_checkOperation.collateralIssue;
|
|
61
61
|
exports.detectDelayedClaim = require_preview_preview_detectDelayedClaim.detectDelayedClaim;
|
|
62
62
|
exports.detectDelayedOperation = require_preview_preview_detectDelayedOperation.detectDelayedOperation;
|
|
63
63
|
exports.extractAdapterCallTraces = require_preview_trace_extractAdapterCallTraces.extractAdapterCallTraces;
|
|
@@ -67,6 +67,7 @@ exports.isCloseOrRepay = require_preview_preview_detectCloseOrRepay.isCloseOrRep
|
|
|
67
67
|
exports.isPoolOperation = require_preview_parse_types.isPoolOperation;
|
|
68
68
|
exports.isRWAOperation = require_preview_parse_types.isRWAOperation;
|
|
69
69
|
exports.makeReplayState = require_preview_preview_replayInnerOperations.makeReplayState;
|
|
70
|
+
exports.marketIssues = require_preview_validate_checkOperation.marketIssues;
|
|
70
71
|
exports.parseFacadeOperationCalldata = require_preview_parse_parseFacadeOperationCalldata.parseFacadeOperationCalldata;
|
|
71
72
|
exports.parseOperationCalldata = require_preview_parse_parseOperationCalldata.parseOperationCalldata;
|
|
72
73
|
exports.parsePoolOperationCalldata = require_preview_parse_parsePoolOperationCalldata.parsePoolOperationCalldata;
|
|
@@ -74,6 +75,7 @@ exports.parseRWAFactoryOperationCalldata = require_preview_parse_parseRWAFactory
|
|
|
74
75
|
exports.previewAdjustCreditAccount = require_preview_preview_previewAdjustCreditAccount.previewAdjustCreditAccount;
|
|
75
76
|
exports.previewCloseOrRepayCreditAccount = require_preview_preview_previewCloseOrRepayCreditAccount.previewCloseOrRepayCreditAccount;
|
|
76
77
|
exports.previewOperation = require_preview_preview_previewOperation.previewOperation;
|
|
78
|
+
exports.quotaCountIssue = require_preview_validate_checkOperation.quotaCountIssue;
|
|
77
79
|
exports.raise = require_onchain_validation_refusal.raise;
|
|
78
80
|
exports.refuse = require_onchain_validation_refusal.refuse;
|
|
79
81
|
exports.replayInnerOperations = require_preview_preview_replayInnerOperations.replayInnerOperations;
|
|
@@ -18,7 +18,7 @@ let viem = require("viem");
|
|
|
18
18
|
* nothing and set a non-fatal `ERROR_UNPRICEABLE_TOKEN` error on the
|
|
19
19
|
* preview.
|
|
20
20
|
*
|
|
21
|
-
* The changes (e.g. `
|
|
21
|
+
* The changes (e.g. `totalDebtChange`) are reported relative to the account
|
|
22
22
|
* state before the whole transaction.
|
|
23
23
|
*
|
|
24
24
|
* @param afterInstant - Account state after the instant part of the
|
|
@@ -188,9 +188,9 @@ function buildAdjustPreview(post, before, collateralWithdrawn, converter, sdk) {
|
|
|
188
188
|
creditAccount: post.creditAccount,
|
|
189
189
|
collateralAdded: [],
|
|
190
190
|
collateralWithdrawn: collateralWithdrawn.toAssets().map((a) => oracle.toTokenAmount(a.token, a.balance)),
|
|
191
|
-
totalValue,
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
totalValue: market.toUnderlyingAmount(totalValue),
|
|
192
|
+
totalDebt: market.toUnderlyingAmount(post.totalDebt),
|
|
193
|
+
totalDebtChange: market.toUnderlyingAmount(post.totalDebt - before.totalDebt),
|
|
194
194
|
quotas: quotas.map((q) => ({
|
|
195
195
|
token: sdk.tokensMeta.mustGetToken(q.token),
|
|
196
196
|
...oracle.toAmount(market.underlying, q.balance)
|
|
@@ -46,9 +46,9 @@ async function previewAdjustCreditAccount(input, operation, options) {
|
|
|
46
46
|
creditAccount: operation.creditAccount,
|
|
47
47
|
collateralAdded: collateralAdded.map((a) => oracle.toTokenAmount(a.token, a.balance)),
|
|
48
48
|
collateralWithdrawn: after.collateralWithdrawn.toAssets().map((a) => oracle.toTokenAmount(a.token, a.balance)),
|
|
49
|
-
totalValue,
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
totalValue: market.toUnderlyingAmount(totalValue),
|
|
50
|
+
totalDebt: market.toUnderlyingAmount(account.totalDebt),
|
|
51
|
+
totalDebtChange: market.toUnderlyingAmount(account.totalDebt - before.totalDebt),
|
|
52
52
|
quotas: quotas.map((q) => ({
|
|
53
53
|
token: sdk.tokensMeta.mustGetToken(q.token),
|
|
54
54
|
...oracle.toAmount(market.underlying, q.balance)
|
|
@@ -57,7 +57,7 @@ function previewRepayCreditAccount(input, operation, permanent, replay) {
|
|
|
57
57
|
name: sdk.marketRegister.findCreditManager(operation.creditManager).name,
|
|
58
58
|
creditAccount: operation.creditAccount,
|
|
59
59
|
collateralAdded: collateralAdded.map((a) => market.priceOracle.toTokenAmount(a.token, a.balance)),
|
|
60
|
-
debtRepaid: before.totalDebt - after.account.totalDebt,
|
|
60
|
+
debtRepaid: market.toUnderlyingAmount(before.totalDebt - after.account.totalDebt),
|
|
61
61
|
collateralWithdrawn: after.collateralWithdrawn.toAssets().map((a) => market.priceOracle.toTokenAmount(a.token, a.balance)),
|
|
62
62
|
error
|
|
63
63
|
};
|
|
@@ -17,7 +17,7 @@ async function previewOpenCreditAccount(input, operation) {
|
|
|
17
17
|
let error = await require_preview_preview_replayInnerOperations.replayInnerOperations(sdk, operation.multicall, state);
|
|
18
18
|
const account = state.account;
|
|
19
19
|
let priceError;
|
|
20
|
-
const
|
|
20
|
+
const netValue = state.collateralAdded.sum((token, balance) => {
|
|
21
21
|
try {
|
|
22
22
|
return oracle.convert(token, market.underlying, balance);
|
|
23
23
|
} catch {
|
|
@@ -32,18 +32,18 @@ async function previewOpenCreditAccount(input, operation) {
|
|
|
32
32
|
error ??= unwrapError ?? priceError;
|
|
33
33
|
const assets = account.balances.toAssets(require_onchain_constants_math.DUST_THRESHOLD);
|
|
34
34
|
const quotas = account.quotas.toAssets(0n);
|
|
35
|
-
const totalValue =
|
|
35
|
+
const totalValue = netValue + account.totalDebt;
|
|
36
36
|
const snap = account.toSnapshot(totalValue);
|
|
37
37
|
const targetAsset = inferTargetAsset(operation.multicall, account.balances);
|
|
38
38
|
return {
|
|
39
39
|
operation: operation.operation,
|
|
40
40
|
creditManager: operation.creditManager,
|
|
41
41
|
name: sdk.marketRegister.findCreditManager(operation.creditManager).name,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
totalValue,
|
|
46
|
-
|
|
42
|
+
targetCollateral: targetAsset ? oracle.toTokenAmount(targetAsset.token, targetAsset.balance) : void 0,
|
|
43
|
+
collateralAdded: collateral.map((a) => oracle.toTokenAmount(a.token, a.balance)),
|
|
44
|
+
netValue: market.toUnderlyingAmount(netValue),
|
|
45
|
+
totalValue: market.toUnderlyingAmount(totalValue),
|
|
46
|
+
totalDebt: market.toUnderlyingAmount(account.totalDebt),
|
|
47
47
|
quotas: quotas.map((q) => ({
|
|
48
48
|
token: sdk.tokensMeta.mustGetToken(q.token),
|
|
49
49
|
...oracle.toAmount(market.underlying, q.balance)
|
|
@@ -31,7 +31,7 @@ function checkOperation(input, options = {}) {
|
|
|
31
31
|
case "RWAOpenCreditAccount":
|
|
32
32
|
case "AdjustCreditAccount": return creditIssues(sdk, preview, options);
|
|
33
33
|
case "CloseCreditAccount":
|
|
34
|
-
case "RepayCreditAccount": return marketIssues(sdk
|
|
34
|
+
case "RepayCreditAccount": return marketIssues(sdk.marketRegister.findCreditManager(preview.creditManager));
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
function poolIssues(sdk, preview, options, isDeposit) {
|
|
@@ -50,8 +50,8 @@ function poolIssues(sdk, preview, options, isDeposit) {
|
|
|
50
50
|
})) || fundingIssue(options, [preview.tokenIn]);
|
|
51
51
|
}
|
|
52
52
|
/** What the market itself refuses, whatever the operation does. */
|
|
53
|
-
function marketIssues(
|
|
54
|
-
const
|
|
53
|
+
function marketIssues(suite) {
|
|
54
|
+
const creditManager = suite.creditManager.address;
|
|
55
55
|
return require_onchain_validation_checks.checkCreditManagerPaused({
|
|
56
56
|
isPaused: suite.isPaused,
|
|
57
57
|
creditManager
|
|
@@ -66,29 +66,42 @@ function creditIssues(sdk, preview, options) {
|
|
|
66
66
|
const market = suite.market;
|
|
67
67
|
const underlying = require_onchain_validation_token.toToken(sdk, market.pool.underlying);
|
|
68
68
|
const isOpening = preview.operation === "OpenCreditAccount" || preview.operation === "RWAOpenCreditAccount";
|
|
69
|
-
return marketIssues(
|
|
70
|
-
debt: preview.
|
|
69
|
+
return marketIssues(suite) || require_onchain_validation_checks.checkDebtInBand({
|
|
70
|
+
debt: preview.totalDebt.value,
|
|
71
71
|
minDebt: suite.creditFacade.minDebt,
|
|
72
72
|
maxDebt: suite.creditFacade.maxDebt,
|
|
73
73
|
underlying,
|
|
74
74
|
allowZero: !isOpening
|
|
75
|
-
}) || borrowIssue(suite, preview, underlying) || forbiddenIssue(suite, preview) ||
|
|
76
|
-
|
|
75
|
+
}) || borrowIssue(suite, preview, underlying) || forbiddenIssue(suite, preview) || quotaCountIssue(suite, preview) || quotaIssue(market, preview, underlying) || collateralIssue(preview, options) || fundingIssue(options, preview.collateralAdded);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A bar that reads nothing but the projected account, so a parsed transaction
|
|
79
|
+
* and a simulated one are held to it by the same code.
|
|
80
|
+
*
|
|
81
|
+
* These stay separate functions rather than one block because the order the
|
|
82
|
+
* checks run in is the answer: `checkOperation` interleaves the checks that
|
|
83
|
+
* need an operation's *delta* between them, and the caller acts on the first
|
|
84
|
+
* issue reported.
|
|
85
|
+
*/
|
|
86
|
+
function quotaCountIssue(suite, projection) {
|
|
87
|
+
return require_onchain_validation_checks.checkQuotaCount({
|
|
88
|
+
count: projection.quotas.filter((q) => q.value > 0n).length,
|
|
77
89
|
max: suite.creditManager.maxEnabledTokens
|
|
78
|
-
})
|
|
90
|
+
});
|
|
79
91
|
}
|
|
80
92
|
/**
|
|
81
93
|
* What the transaction draws, against what the market can lend right now.
|
|
82
94
|
*
|
|
83
95
|
* Only a draw is weighed: repaying, or leaving the debt alone, can never exceed
|
|
84
|
-
* a ceiling. Opening borrows the whole debt; adjusting borrows
|
|
96
|
+
* a ceiling. Opening borrows the whole debt; adjusting borrows
|
|
97
|
+
* `totalDebtChange`.
|
|
85
98
|
*
|
|
86
99
|
* The engine holds every simulation to this already (`assertCanBorrow`), so
|
|
87
100
|
* this is here for the transactions it never saw — a pasted calldata reaches
|
|
88
101
|
* the confirm screen with nothing else standing between it and a revert.
|
|
89
102
|
*/
|
|
90
103
|
function borrowIssue(suite, preview, underlying) {
|
|
91
|
-
const drawn = preview.operation === "AdjustCreditAccount" ? preview.
|
|
104
|
+
const drawn = preview.operation === "AdjustCreditAccount" ? preview.totalDebtChange.value : preview.totalDebt.value;
|
|
92
105
|
if (drawn <= 0n) return null;
|
|
93
106
|
const { limit, binding } = require_onchain_accounts_intents_guards.borrowable(suite);
|
|
94
107
|
return require_onchain_validation_checks.checkBorrowLimit({
|
|
@@ -98,12 +111,27 @@ function borrowIssue(suite, preview, underlying) {
|
|
|
98
111
|
underlying
|
|
99
112
|
});
|
|
100
113
|
}
|
|
101
|
-
/**
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
/**
|
|
115
|
+
* The account against whichever bars the caller holds it to.
|
|
116
|
+
*
|
|
117
|
+
* A loan-free account is nothing to weigh: the health factor reports its
|
|
118
|
+
* zero-debt sentinel and no bar applies.
|
|
119
|
+
*
|
|
120
|
+
* {@inheritDoc quotaCountIssue}
|
|
121
|
+
*/
|
|
122
|
+
function collateralIssue(projection, options) {
|
|
123
|
+
const { minHealthFactor, minSafeHealthFactor, currentHealthFactor } = options;
|
|
124
|
+
if (projection.totalDebt.value === 0n) return null;
|
|
125
|
+
return (minHealthFactor === void 0 ? null : require_onchain_validation_checks.checkCollateralised({
|
|
126
|
+
healthFactor: projection.healthFactor,
|
|
127
|
+
required: minHealthFactor,
|
|
128
|
+
safePrices: false,
|
|
129
|
+
improvesFrom: currentHealthFactor
|
|
130
|
+
})) || (minSafeHealthFactor === void 0 || projection.safeHealthFactor === void 0 ? null : require_onchain_validation_checks.checkCollateralised({
|
|
131
|
+
healthFactor: projection.safeHealthFactor,
|
|
132
|
+
required: minSafeHealthFactor,
|
|
133
|
+
safePrices: true
|
|
134
|
+
}));
|
|
107
135
|
}
|
|
108
136
|
/** The wallet's side of the operation, against the balances it was given. */
|
|
109
137
|
function fundingIssue(options, puts) {
|
|
@@ -119,12 +147,6 @@ function fundingIssue(options, puts) {
|
|
|
119
147
|
}
|
|
120
148
|
return null;
|
|
121
149
|
}
|
|
122
|
-
/** What the wallet puts in, which is what its balances have to cover. */
|
|
123
|
-
function collateralOf(preview) {
|
|
124
|
-
if ("collateral" in preview) return preview.collateral;
|
|
125
|
-
if ("collateralAdded" in preview) return preview.collateralAdded;
|
|
126
|
-
return [];
|
|
127
|
-
}
|
|
128
150
|
function forbiddenIssue(suite, preview) {
|
|
129
151
|
const obtained = preview.operation === "AdjustCreditAccount" ? preview.assetsChange : preview.assets;
|
|
130
152
|
const forbidden = suite.forbiddenTokens;
|
|
@@ -154,20 +176,8 @@ function quotaIssue(market, preview, underlying) {
|
|
|
154
176
|
}
|
|
155
177
|
return null;
|
|
156
178
|
}
|
|
157
|
-
/** The two collateral bars, shared by the preview and the simulation paths. */
|
|
158
|
-
function collateralIssuesOf(factors, options) {
|
|
159
|
-
const { minHealthFactor, minSafeHealthFactor, currentHealthFactor } = options;
|
|
160
|
-
return (minHealthFactor === void 0 ? null : require_onchain_validation_checks.checkCollateralised({
|
|
161
|
-
healthFactor: factors.healthFactor,
|
|
162
|
-
required: minHealthFactor,
|
|
163
|
-
safePrices: false,
|
|
164
|
-
improvesFrom: currentHealthFactor
|
|
165
|
-
})) || (minSafeHealthFactor === void 0 || factors.safeHealthFactor === void 0 ? null : require_onchain_validation_checks.checkCollateralised({
|
|
166
|
-
healthFactor: factors.safeHealthFactor,
|
|
167
|
-
required: minSafeHealthFactor,
|
|
168
|
-
safePrices: true
|
|
169
|
-
}));
|
|
170
|
-
}
|
|
171
179
|
//#endregion
|
|
172
180
|
exports.checkOperation = checkOperation;
|
|
173
|
-
exports.
|
|
181
|
+
exports.collateralIssue = collateralIssue;
|
|
182
|
+
exports.marketIssues = marketIssues;
|
|
183
|
+
exports.quotaCountIssue = quotaCountIssue;
|
|
@@ -27,26 +27,13 @@ const require_preview_validate_checkOperation = require("./checkOperation.js");
|
|
|
27
27
|
function checkSimulation(input, options = {}) {
|
|
28
28
|
const { sdk, state, creditManager } = input;
|
|
29
29
|
const suite = sdk.marketRegister.findCreditManager(creditManager);
|
|
30
|
-
return require_onchain_validation_checks.
|
|
31
|
-
|
|
32
|
-
creditManager
|
|
33
|
-
}) || require_onchain_validation_checks.checkMarketExpired({
|
|
34
|
-
isExpired: suite.isExpired,
|
|
35
|
-
creditManager,
|
|
36
|
-
expirationDate: suite.creditFacade.expirationDate
|
|
37
|
-
}) || require_onchain_validation_checks.checkDebtInBand({
|
|
38
|
-
debt: state.accountDebt,
|
|
30
|
+
return require_preview_validate_checkOperation.marketIssues(suite) || require_onchain_validation_checks.checkDebtInBand({
|
|
31
|
+
debt: state.totalDebt.value,
|
|
39
32
|
minDebt: suite.creditFacade.minDebt,
|
|
40
33
|
maxDebt: suite.creditFacade.maxDebt,
|
|
41
34
|
underlying: require_onchain_validation_token.toToken(sdk, suite.market.pool.underlying),
|
|
42
35
|
allowZero: true
|
|
43
|
-
}) ||
|
|
44
|
-
count: Object.values(state.quotas).filter((q) => q.balance > 0n).length,
|
|
45
|
-
max: suite.creditManager.maxEnabledTokens
|
|
46
|
-
}) || (state.accountDebt === 0n ? null : require_preview_validate_checkOperation.collateralIssuesOf({
|
|
47
|
-
healthFactor: state.healthFactor,
|
|
48
|
-
safeHealthFactor: state.safeHealthFactor
|
|
49
|
-
}, options));
|
|
36
|
+
}) || require_preview_validate_checkOperation.quotaCountIssue(suite, state) || require_preview_validate_checkOperation.collateralIssue(state, options);
|
|
50
37
|
}
|
|
51
38
|
//#endregion
|
|
52
39
|
exports.checkSimulation = checkSimulation;
|
|
@@ -3,4 +3,6 @@ const require_preview_validate_checkOperation = require("./checkOperation.js");
|
|
|
3
3
|
const require_preview_validate_checkSimulation = require("./checkSimulation.js");
|
|
4
4
|
exports.checkOperation = require_preview_validate_checkOperation.checkOperation;
|
|
5
5
|
exports.checkSimulation = require_preview_validate_checkSimulation.checkSimulation;
|
|
6
|
-
exports.
|
|
6
|
+
exports.collateralIssue = require_preview_validate_checkOperation.collateralIssue;
|
|
7
|
+
exports.marketIssues = require_preview_validate_checkOperation.marketIssues;
|
|
8
|
+
exports.quotaCountIssue = require_preview_validate_checkOperation.quotaCountIssue;
|
|
@@ -25,21 +25,24 @@ function poolTx(sdk, request) {
|
|
|
25
25
|
const { pool, wallet, sim } = request;
|
|
26
26
|
const { tokenIn, tokenOut } = sim.preview;
|
|
27
27
|
if (request.op === "deposit") {
|
|
28
|
-
const meta = sdk.pools.getDepositMetadata(pool, tokenIn.token, tokenOut.token);
|
|
28
|
+
const meta = sdk.pools.getDepositMetadata(pool, tokenIn.token.address, tokenOut.token.address);
|
|
29
29
|
const result = sdk.pools.addLiquidity({
|
|
30
30
|
pool,
|
|
31
31
|
wallet,
|
|
32
|
-
collateral:
|
|
32
|
+
collateral: {
|
|
33
|
+
token: tokenIn.token.address,
|
|
34
|
+
balance: tokenIn.value
|
|
35
|
+
},
|
|
33
36
|
meta
|
|
34
37
|
});
|
|
35
|
-
if (!result) throw new Error(`pool ${pool} takes no deposit transaction for ${tokenIn.token} (${meta.type})`);
|
|
38
|
+
if (!result) throw new Error(`pool ${pool} takes no deposit transaction for ${tokenIn.token.address} (${meta.type})`);
|
|
36
39
|
return result.tx;
|
|
37
40
|
}
|
|
38
|
-
const meta = sdk.pools.getWithdrawalMetadata(pool, tokenIn.token, tokenOut.token);
|
|
41
|
+
const meta = sdk.pools.getWithdrawalMetadata(pool, tokenIn.token.address, tokenOut.token.address);
|
|
39
42
|
return sdk.pools.removeLiquidity({
|
|
40
43
|
pool,
|
|
41
44
|
wallet,
|
|
42
|
-
amount: request.op === "withdraw" ? tokenOut.
|
|
45
|
+
amount: request.op === "withdraw" ? tokenOut.value : tokenIn.value,
|
|
43
46
|
permit: void 0,
|
|
44
47
|
meta,
|
|
45
48
|
mode: request.op === "withdraw" ? "withdraw" : "redeem"
|
|
@@ -53,7 +56,7 @@ async function openTx(sdk, request) {
|
|
|
53
56
|
to: wallet,
|
|
54
57
|
collateral,
|
|
55
58
|
ethAmount,
|
|
56
|
-
debt: preview.
|
|
59
|
+
debt: preview.totalDebt.value,
|
|
57
60
|
calls: preview.calls,
|
|
58
61
|
averageQuota: preview.averageQuota,
|
|
59
62
|
minQuota: preview.minQuota,
|
|
@@ -66,7 +66,10 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
|
|
|
66
66
|
tokenOut
|
|
67
67
|
});
|
|
68
68
|
const call = pools.addLiquidity({
|
|
69
|
-
collateral:
|
|
69
|
+
collateral: {
|
|
70
|
+
token: preview.tokenIn.token.address,
|
|
71
|
+
balance: preview.tokenIn.value
|
|
72
|
+
},
|
|
70
73
|
pool: pool.pool,
|
|
71
74
|
wallet: params.wallet,
|
|
72
75
|
meta: pools.getDepositMetadata(pool.pool, tokenIn, tokenOut)
|
|
@@ -30,7 +30,7 @@ function maxWithdrawCollateral(props) {
|
|
|
30
30
|
const underlying = market.pool.underlying;
|
|
31
31
|
const target = creditAccount.tokens.find((t) => eq(t.token, token));
|
|
32
32
|
if (!target || target.balance <= 10n) return 0n;
|
|
33
|
-
if (creditAccount.
|
|
33
|
+
if (creditAccount.totalDebt === 0n) return target.balance;
|
|
34
34
|
const masked = creditAccount.enabledTokensMask !== 0n;
|
|
35
35
|
const counts = (t) => t.balance > 10n && (!masked || (t.mask & creditAccount.enabledTokensMask) !== 0n);
|
|
36
36
|
/** What a holding backs, in the check's units: USD × PERCENTAGE_FACTOR. */
|
|
@@ -47,7 +47,7 @@ function maxWithdrawCollateral(props) {
|
|
|
47
47
|
if (eq(t.token, token) || !counts(t)) continue;
|
|
48
48
|
otherMoney += weigh(t);
|
|
49
49
|
}
|
|
50
|
-
const borrowed = usd(priceOracle, underlying, creditAccount.
|
|
50
|
+
const borrowed = usd(priceOracle, underlying, creditAccount.totalDebt);
|
|
51
51
|
if (borrowed === void 0 || borrowed <= 0n) return 0n;
|
|
52
52
|
const required = borrowed * targetHF;
|
|
53
53
|
if (required <= otherMoney) return target.balance;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { calcPositionLeverage } from "../../market/math.js";
|
|
1
2
|
import { IntentPreviewError } from "../../validation/refusal.js";
|
|
2
3
|
import { assertCanBorrow, assertCollateralised, assertGrowthAllowed, assertMarketOperable, assertQuotaHeadroom } from "./guards.js";
|
|
3
4
|
import { assertDebtInBand, assertLeverageAtLeastOne, debtForLeverage } from "./math.js";
|
|
@@ -37,7 +38,7 @@ async function previewOpenStrategy(props) {
|
|
|
37
38
|
underlying,
|
|
38
39
|
enabledTokensMask: 0n,
|
|
39
40
|
totalDebtUSD: 0n,
|
|
40
|
-
|
|
41
|
+
totalDebt: 0n,
|
|
41
42
|
tokens: []
|
|
42
43
|
};
|
|
43
44
|
assertDebtInBand(sdk, debt, suite.creditFacade, underlying);
|
|
@@ -87,6 +88,7 @@ async function previewOpenStrategy(props) {
|
|
|
87
88
|
const projectedPool = { availableLiquidityChange: -debt };
|
|
88
89
|
const metrics = {
|
|
89
90
|
healthFactor: sdk.positions.healthFactor(snapshot),
|
|
91
|
+
safeHealthFactor: sdk.positions.healthFactor(snapshot, { safePrices: true }),
|
|
90
92
|
borrowRate: sdk.positions.borrowRate(snapshot, projectedPool),
|
|
91
93
|
timeToLiquidation: sdk.positions.timeToLiquidation(snapshot, projectedPool),
|
|
92
94
|
liquidationPrice: sdk.positions.liquidationPrice(snapshot)
|
|
@@ -98,9 +100,10 @@ async function previewOpenStrategy(props) {
|
|
|
98
100
|
toUnderlying: (from, amount) => convert(from, underlying, amount)
|
|
99
101
|
});
|
|
100
102
|
return {
|
|
101
|
-
debt,
|
|
102
|
-
|
|
103
|
-
totalValue: margin + debt,
|
|
103
|
+
totalDebt: market.toUnderlyingAmount(debt),
|
|
104
|
+
netValue: market.toUnderlyingAmount(margin),
|
|
105
|
+
totalValue: market.toUnderlyingAmount(margin + debt),
|
|
106
|
+
leverage: calcPositionLeverage(margin + debt, debt),
|
|
104
107
|
priceImpact,
|
|
105
108
|
averageAssets: averageAssets.map(priced),
|
|
106
109
|
minAssets: minAssets.map(priced),
|
|
@@ -35,7 +35,7 @@ async function realize(steps, props) {
|
|
|
35
35
|
const ledger = new OperationLedger({
|
|
36
36
|
initialAssets: creditAccount.tokens,
|
|
37
37
|
underlying,
|
|
38
|
-
debt: creditAccount.
|
|
38
|
+
debt: creditAccount.totalDebt,
|
|
39
39
|
convert: price
|
|
40
40
|
});
|
|
41
41
|
const operations = [];
|
|
@@ -271,7 +271,7 @@ async function realize(steps, props) {
|
|
|
271
271
|
totalDebt: debt,
|
|
272
272
|
totalValue
|
|
273
273
|
};
|
|
274
|
-
const projectedPool = { availableLiquidityChange: creditAccount.
|
|
274
|
+
const projectedPool = { availableLiquidityChange: creditAccount.totalDebt - debt };
|
|
275
275
|
const metrics = {
|
|
276
276
|
healthFactor: sdk.positions.healthFactor(snapshot),
|
|
277
277
|
safeHealthFactor: paysOut ? sdk.positions.healthFactor(snapshot, { safePrices: true }) : void 0,
|
|
@@ -285,12 +285,16 @@ async function realize(steps, props) {
|
|
|
285
285
|
netValue: totalValue - debt,
|
|
286
286
|
toUnderlying: (from, amount) => price(from, underlying, amount)
|
|
287
287
|
});
|
|
288
|
+
const oracle = market.priceOracle;
|
|
288
289
|
const state = {
|
|
289
|
-
totalValue,
|
|
290
|
-
|
|
290
|
+
totalValue: market.toUnderlyingAmount(totalValue),
|
|
291
|
+
totalDebt: market.toUnderlyingAmount(debt),
|
|
291
292
|
leverage: calcPositionLeverage(totalValue, debt),
|
|
292
|
-
assets: assets.map((a) =>
|
|
293
|
-
quotas: quotasAfter
|
|
293
|
+
assets: assets.map((a) => oracle.toTokenAmount(a.token, a.balance)),
|
|
294
|
+
quotas: Object.values(quotasAfter).map((q) => ({
|
|
295
|
+
token: sdk.tokensMeta.mustGetToken(q.token),
|
|
296
|
+
...oracle.toAmount(underlying, q.balance)
|
|
297
|
+
})),
|
|
294
298
|
priceImpact,
|
|
295
299
|
...metrics
|
|
296
300
|
};
|
|
@@ -102,15 +102,16 @@ function projectedClaimable(request, phantom, phantomAmount, claim) {
|
|
|
102
102
|
*/
|
|
103
103
|
function sliceAfter(creditAccount, after) {
|
|
104
104
|
const masks = new Map(creditAccount.tokens.map((t) => [t.token.toLowerCase(), t.mask]));
|
|
105
|
+
const quotas = new Map(after.quotas.map((q) => [q.token.address.toLowerCase(), q.value]));
|
|
105
106
|
return {
|
|
106
107
|
...creditAccount,
|
|
107
|
-
|
|
108
|
+
totalDebt: after.totalDebt.value,
|
|
108
109
|
tokens: after.assets.map((a) => {
|
|
109
110
|
const token = a.token.address.toLowerCase();
|
|
110
111
|
return {
|
|
111
112
|
token,
|
|
112
113
|
balance: a.value,
|
|
113
|
-
quota:
|
|
114
|
+
quota: quotas.get(token) ?? 0n,
|
|
114
115
|
mask: masks.get(token) ?? 0n,
|
|
115
116
|
success: true
|
|
116
117
|
};
|
|
@@ -144,13 +144,30 @@ function buildMockSdk(args) {
|
|
|
144
144
|
return price;
|
|
145
145
|
};
|
|
146
146
|
const poolPaused = args.poolPaused ?? false;
|
|
147
|
+
/** {@inheritDoc MarketSuite.toUnderlyingAmount} */
|
|
148
|
+
const toUnderlyingAmount = (value) => {
|
|
149
|
+
const usd = safeUsd(args.underlying, value);
|
|
150
|
+
return {
|
|
151
|
+
token: tokenOf(args.rwaAssets?.[args.underlying.toLowerCase()] ?? args.underlying),
|
|
152
|
+
value,
|
|
153
|
+
valueUsd: usd === null ? null : usdToNumber(usd)
|
|
154
|
+
};
|
|
155
|
+
};
|
|
147
156
|
const market = {
|
|
157
|
+
toUnderlyingAmount,
|
|
148
158
|
priceOracle: {
|
|
149
159
|
convert,
|
|
150
160
|
safeConvert,
|
|
151
161
|
mainPrice: mainPriceOf,
|
|
152
162
|
reservePrice: reservePriceOf,
|
|
153
163
|
convertToUSD: _convertToUSD,
|
|
164
|
+
toAmount: (token, value) => {
|
|
165
|
+
const usd = safeUsd(token, value);
|
|
166
|
+
return {
|
|
167
|
+
value,
|
|
168
|
+
valueUsd: usd === null ? null : usdToNumber(usd)
|
|
169
|
+
};
|
|
170
|
+
},
|
|
154
171
|
toTokenAmount: (token, value) => {
|
|
155
172
|
const usd = safeUsd(token, value);
|
|
156
173
|
return {
|
|
@@ -349,7 +366,7 @@ function payloadOf(slice) {
|
|
|
349
366
|
owner: slice.creditAccount,
|
|
350
367
|
expirationDate: 0,
|
|
351
368
|
enabledTokensMask: slice.enabledTokensMask,
|
|
352
|
-
debt: slice.
|
|
369
|
+
debt: slice.totalDebt,
|
|
353
370
|
accruedInterest: 0n,
|
|
354
371
|
accruedFees: 0n,
|
|
355
372
|
totalDebtUSD: slice.totalDebtUSD,
|
|
@@ -31,7 +31,7 @@ const case_position_token = {
|
|
|
31
31
|
amount: ADD_ANY
|
|
32
32
|
},
|
|
33
33
|
tokens: [caToken(UND, BASE_UND)],
|
|
34
|
-
|
|
34
|
+
totalDebt: DEBT,
|
|
35
35
|
totalValue: BASE_UND + valueInUnd(ADD_ANY, ANY),
|
|
36
36
|
ops: [{
|
|
37
37
|
type: "addCollateral",
|
|
@@ -56,7 +56,7 @@ const case_underlying = {
|
|
|
56
56
|
amount: ADD_UND
|
|
57
57
|
},
|
|
58
58
|
tokens: [caToken(ANY, ADD_ANY, QUOTA_ANY)],
|
|
59
|
-
|
|
59
|
+
totalDebt: DEBT,
|
|
60
60
|
totalValue: valueInUnd(ADD_ANY, ANY) + ADD_UND,
|
|
61
61
|
ops: [{
|
|
62
62
|
type: "addCollateral",
|
|
@@ -73,7 +73,7 @@ const case_rwa_asset = {
|
|
|
73
73
|
amount: ADD_RWA
|
|
74
74
|
},
|
|
75
75
|
tokens: [caToken(UND, BASE_UND)],
|
|
76
|
-
|
|
76
|
+
totalDebt: DEBT,
|
|
77
77
|
totalValue: BASE_UND + valueInUnd(ADD_RWA, RWA_ASSET),
|
|
78
78
|
ops: [{
|
|
79
79
|
type: "addCollateral",
|
|
@@ -98,7 +98,7 @@ function buildAddCollateralProps(c, sdk) {
|
|
|
98
98
|
return {
|
|
99
99
|
intent: c.intent,
|
|
100
100
|
creditAccount: buildFixtureCreditAccount({
|
|
101
|
-
|
|
101
|
+
totalDebt: c.totalDebt,
|
|
102
102
|
tokens: c.tokens
|
|
103
103
|
}),
|
|
104
104
|
sdk,
|