@gearbox-protocol/sdk 17.0.0 → 17.1.0-next.2

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.
@@ -24,20 +24,23 @@ function proportionalDebt(position, collateralDelta) {
24
24
  if (position.collateral <= 0n) throw new require_onchain_validation_raise.IntentPreviewError(require_model_errors_operation_errors.insufficientBalance(), "cannot preserve leverage on an account with no collateral");
25
25
  return position.debt * collateralDelta / position.collateral;
26
26
  }
27
+ /** Share of the debt kept above `minDebt` for interest accrued before sending. */
28
+ const WITHDRAW_DEBT_MARGIN = 1n;
27
29
  /**
28
30
  * Largest withdrawal (in underlying) that {@link proportionalDebt} can still
29
- * pay for: the repayment it implies leaves debt at or above `minDebt`, and
31
+ * pay for: the repayment it implies leaves debt at or above `minDebt` plus
32
+ * {@link WITHDRAW_DEBT_MARGIN} of the debt, and
30
33
  * strictly less than the collateral goes — the last unit closes the account
31
34
  * rather than shrinks it. `0n` when the debt already sits below `minDebt`.
32
35
  *
33
- * Solves `floor(D0 · W / C0) ≤ D0 − minDebt` for `W`.
36
+ * Solves `floor(D0 · W / C0) ≤ D0 − minDebt − margin` for `W`.
34
37
  */
35
38
  function maxProportionalWithdrawal(position, debtLimits) {
36
39
  const { debt, collateral } = position;
37
40
  if (collateral <= 0n) return 0n;
38
41
  const allButLast = collateral - 1n;
39
42
  if (debt === 0n) return allButLast;
40
- const repayable = debt - debtLimits.minDebt;
43
+ const repayable = debt - debtLimits.minDebt - debt * WITHDRAW_DEBT_MARGIN / require_onchain_constants_math.PERCENTAGE_FACTOR;
41
44
  if (repayable < 0n) return 0n;
42
45
  const bound = require_onchain_utils_bigint_math.BigIntMath.ceilDiv(collateral * (repayable + 1n), debt) - 1n;
43
46
  return bound < allButLast ? bound : allButLast;
@@ -155,7 +155,7 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
155
155
  tokenIn: toTokenAmount(tokenIn, pool.pool.underlyingToShares(amount * require_onchain_constants_math.PERCENTAGE_FACTOR / (require_onchain_constants_math.PERCENTAGE_FACTOR - pool.pool.withdrawFee), true)),
156
156
  tokenOut: toTokenAmount(tokenOut, amount),
157
157
  zapper: zapper?.baseParams.addr,
158
- availableLiquidity: this.#withdrawableLiquidity(market)
158
+ availableLiquidity: this.withdrawableLiquidity(poolAddr)
159
159
  };
160
160
  }
161
161
  /**
@@ -177,7 +177,7 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
177
177
  tokenIn: toTokenAmount(tokenIn, amount),
178
178
  tokenOut: toTokenAmount(tokenOut, pool.pool.sharesToUnderlying(amount) * (require_onchain_constants_math.PERCENTAGE_FACTOR - pool.pool.withdrawFee) / require_onchain_constants_math.PERCENTAGE_FACTOR),
179
179
  zapper: zapper?.baseParams.addr,
180
- availableLiquidity: this.#withdrawableLiquidity(market)
180
+ availableLiquidity: this.withdrawableLiquidity(poolAddr)
181
181
  };
182
182
  }
183
183
  /**
@@ -406,12 +406,11 @@ var PoolService = class extends require_onchain_base_SDKConstruct.SDKConstruct {
406
406
  };
407
407
  }
408
408
  /**
409
- * The most the pool can actually hand over right now, trimmed slightly so a
410
- * withdrawal sized against it does not fail on rounding.
411
- **/
412
- #withdrawableLiquidity(market) {
413
- const { pool } = market;
414
- return market.priceOracle.toAmount(pool.underlying, pool.pool.availableLiquidity * 99999n / 100000n);
409
+ * {@inheritDoc IPoolsService.withdrawableLiquidity}
410
+ */
411
+ withdrawableLiquidity(pool) {
412
+ const market = this.sdk.marketRegister.findByPool(pool);
413
+ return market.priceOracle.toAmount(market.pool.underlying, market.pool.pool.availableLiquidity * 99999n / 100000n);
415
414
  }
416
415
  };
417
416
  //#endregion
@@ -4,13 +4,7 @@ const require_onchain_validation_checks_checkPoolPaused = require("../checks/che
4
4
  const require_onchain_validation_checks_checkPoolSunset = require("../checks/checkPoolSunset.js");
5
5
  require("../checks/index.js");
6
6
  //#region src/onchain/validation/bundles/checkPoolOperation.ts
7
- /**
8
- * What the pool's own state stops, whichever side of it the wallet is on.
9
- *
10
- * The liquidity read is the market's rather than the trimmed figure a
11
- * simulation carries: a withdrawal sized against that figure has to pass the
12
- * check that follows it.
13
- */
7
+ /** What the pool's own state stops, whichever side of it the wallet is on. */
14
8
  function checkPoolOperation(args) {
15
9
  const { sdk, pool, isDeposit, tokenOut } = args;
16
10
  const market = sdk.marketRegister.findByPool(pool);
@@ -26,7 +20,7 @@ function checkPoolOperation(args) {
26
20
  }),
27
21
  ...isDeposit ? [] : require_onchain_validation_checks_checkPoolLiquidity.checkPoolLiquidity({
28
22
  requested: tokenOut.value,
29
- available: market.pool.pool.availableLiquidity,
23
+ available: sdk.pools.withdrawableLiquidity(pool).value,
30
24
  underlying: tokenOut.token
31
25
  })
32
26
  ];
@@ -4,17 +4,10 @@ require("../../../model/index.js");
4
4
  const require_onchain_validation_helpers_amount = require("../helpers/amount.js");
5
5
  require("../helpers/index.js");
6
6
  //#region src/onchain/validation/checks/checkPoolLiquidity.ts
7
- /**
8
- * What the pool holds, against what is being taken out of it.
9
- *
10
- * The operator is not `checkBorrowLimit`'s: a pool holding exactly the amount
11
- * requested still cannot serve it, so equality is already a refusal. That is
12
- * the rule the legacy withdrawal validator enforced and it is preserved to the
13
- * unit.
14
- */
7
+ /** What the pool can hand over, against what is being taken out of it. */
15
8
  function checkPoolLiquidity(args) {
16
9
  const { requested, available, underlying } = args;
17
- if (requested < available) return [];
10
+ if (requested <= available) return [];
18
11
  return [require_model_errors_operation_errors.insufficientPoolLiquidity({
19
12
  requested: require_onchain_validation_helpers_amount.amountOf(underlying, requested),
20
13
  available: require_onchain_validation_helpers_amount.amountOf(underlying, available),
@@ -1,5 +1,5 @@
1
1
  import { BigIntMath } from "../../utils/bigint-math.js";
2
- import { LEVERAGE_DECIMALS } from "../../constants/math.js";
2
+ import { LEVERAGE_DECIMALS, PERCENTAGE_FACTOR } from "../../constants/math.js";
3
3
  import { insufficientBalance } from "../../../model/errors/operation-errors.js";
4
4
  import "../../../model/index.js";
5
5
  import { toToken } from "../../validation/helpers/token.js";
@@ -23,20 +23,23 @@ function proportionalDebt(position, collateralDelta) {
23
23
  if (position.collateral <= 0n) throw new IntentPreviewError(insufficientBalance(), "cannot preserve leverage on an account with no collateral");
24
24
  return position.debt * collateralDelta / position.collateral;
25
25
  }
26
+ /** Share of the debt kept above `minDebt` for interest accrued before sending. */
27
+ const WITHDRAW_DEBT_MARGIN = 1n;
26
28
  /**
27
29
  * Largest withdrawal (in underlying) that {@link proportionalDebt} can still
28
- * pay for: the repayment it implies leaves debt at or above `minDebt`, and
30
+ * pay for: the repayment it implies leaves debt at or above `minDebt` plus
31
+ * {@link WITHDRAW_DEBT_MARGIN} of the debt, and
29
32
  * strictly less than the collateral goes — the last unit closes the account
30
33
  * rather than shrinks it. `0n` when the debt already sits below `minDebt`.
31
34
  *
32
- * Solves `floor(D0 · W / C0) ≤ D0 − minDebt` for `W`.
35
+ * Solves `floor(D0 · W / C0) ≤ D0 − minDebt − margin` for `W`.
33
36
  */
34
37
  function maxProportionalWithdrawal(position, debtLimits) {
35
38
  const { debt, collateral } = position;
36
39
  if (collateral <= 0n) return 0n;
37
40
  const allButLast = collateral - 1n;
38
41
  if (debt === 0n) return allButLast;
39
- const repayable = debt - debtLimits.minDebt;
42
+ const repayable = debt - debtLimits.minDebt - debt * WITHDRAW_DEBT_MARGIN / PERCENTAGE_FACTOR;
40
43
  if (repayable < 0n) return 0n;
41
44
  const bound = BigIntMath.ceilDiv(collateral * (repayable + 1n), debt) - 1n;
42
45
  return bound < allButLast ? bound : allButLast;
@@ -154,7 +154,7 @@ var PoolService = class extends SDKConstruct {
154
154
  tokenIn: toTokenAmount(tokenIn, pool.pool.underlyingToShares(amount * PERCENTAGE_FACTOR / (PERCENTAGE_FACTOR - pool.pool.withdrawFee), true)),
155
155
  tokenOut: toTokenAmount(tokenOut, amount),
156
156
  zapper: zapper?.baseParams.addr,
157
- availableLiquidity: this.#withdrawableLiquidity(market)
157
+ availableLiquidity: this.withdrawableLiquidity(poolAddr)
158
158
  };
159
159
  }
160
160
  /**
@@ -176,7 +176,7 @@ var PoolService = class extends SDKConstruct {
176
176
  tokenIn: toTokenAmount(tokenIn, amount),
177
177
  tokenOut: toTokenAmount(tokenOut, pool.pool.sharesToUnderlying(amount) * (PERCENTAGE_FACTOR - pool.pool.withdrawFee) / PERCENTAGE_FACTOR),
178
178
  zapper: zapper?.baseParams.addr,
179
- availableLiquidity: this.#withdrawableLiquidity(market)
179
+ availableLiquidity: this.withdrawableLiquidity(poolAddr)
180
180
  };
181
181
  }
182
182
  /**
@@ -405,12 +405,11 @@ var PoolService = class extends SDKConstruct {
405
405
  };
406
406
  }
407
407
  /**
408
- * The most the pool can actually hand over right now, trimmed slightly so a
409
- * withdrawal sized against it does not fail on rounding.
410
- **/
411
- #withdrawableLiquidity(market) {
412
- const { pool } = market;
413
- return market.priceOracle.toAmount(pool.underlying, pool.pool.availableLiquidity * 99999n / 100000n);
408
+ * {@inheritDoc IPoolsService.withdrawableLiquidity}
409
+ */
410
+ withdrawableLiquidity(pool) {
411
+ const market = this.sdk.marketRegister.findByPool(pool);
412
+ return market.priceOracle.toAmount(market.pool.underlying, market.pool.pool.availableLiquidity * 99999n / 100000n);
414
413
  }
415
414
  };
416
415
  //#endregion
@@ -3,13 +3,7 @@ import { checkPoolPaused } from "../checks/checkPoolPaused.js";
3
3
  import { checkPoolSunset } from "../checks/checkPoolSunset.js";
4
4
  import "../checks/index.js";
5
5
  //#region src/onchain/validation/bundles/checkPoolOperation.ts
6
- /**
7
- * What the pool's own state stops, whichever side of it the wallet is on.
8
- *
9
- * The liquidity read is the market's rather than the trimmed figure a
10
- * simulation carries: a withdrawal sized against that figure has to pass the
11
- * check that follows it.
12
- */
6
+ /** What the pool's own state stops, whichever side of it the wallet is on. */
13
7
  function checkPoolOperation(args) {
14
8
  const { sdk, pool, isDeposit, tokenOut } = args;
15
9
  const market = sdk.marketRegister.findByPool(pool);
@@ -25,7 +19,7 @@ function checkPoolOperation(args) {
25
19
  }),
26
20
  ...isDeposit ? [] : checkPoolLiquidity({
27
21
  requested: tokenOut.value,
28
- available: market.pool.pool.availableLiquidity,
22
+ available: sdk.pools.withdrawableLiquidity(pool).value,
29
23
  underlying: tokenOut.token
30
24
  })
31
25
  ];
@@ -3,17 +3,10 @@ import "../../../model/index.js";
3
3
  import { amountOf } from "../helpers/amount.js";
4
4
  import "../helpers/index.js";
5
5
  //#region src/onchain/validation/checks/checkPoolLiquidity.ts
6
- /**
7
- * What the pool holds, against what is being taken out of it.
8
- *
9
- * The operator is not `checkBorrowLimit`'s: a pool holding exactly the amount
10
- * requested still cannot serve it, so equality is already a refusal. That is
11
- * the rule the legacy withdrawal validator enforced and it is preserved to the
12
- * unit.
13
- */
6
+ /** What the pool can hand over, against what is being taken out of it. */
14
7
  function checkPoolLiquidity(args) {
15
8
  const { requested, available, underlying } = args;
16
- if (requested < available) return [];
9
+ if (requested <= available) return [];
17
10
  return [insufficientPoolLiquidity({
18
11
  requested: amountOf(underlying, requested),
19
12
  available: amountOf(underlying, available),
@@ -30,11 +30,12 @@ declare function debtForLeverage(collateral: bigint, leverage: bigint): bigint;
30
30
  declare function proportionalDebt(position: Position, collateralDelta: bigint): bigint;
31
31
  /**
32
32
  * Largest withdrawal (in underlying) that {@link proportionalDebt} can still
33
- * pay for: the repayment it implies leaves debt at or above `minDebt`, and
33
+ * pay for: the repayment it implies leaves debt at or above `minDebt` plus
34
+ * {@link WITHDRAW_DEBT_MARGIN} of the debt, and
34
35
  * strictly less than the collateral goes — the last unit closes the account
35
36
  * rather than shrinks it. `0n` when the debt already sits below `minDebt`.
36
37
  *
37
- * Solves `floor(D0 · W / C0) ≤ D0 − minDebt` for `W`.
38
+ * Solves `floor(D0 · W / C0) ≤ D0 − minDebt − margin` for `W`.
38
39
  */
39
40
  declare function maxProportionalWithdrawal(position: Position, debtLimits: DebtLimits): bigint;
40
41
  /** Total leverage cannot drop below 1x — that would be negative debt. */
@@ -1,3 +1,4 @@
1
+ import { Amount } from "../../model/primitives.js";
1
2
  import { PoolPosition } from "../../model/positions.js";
2
3
  import "../../model/index.js";
3
4
  import { AddLiquidityProps, DepositMetadata, IPoolsService, ListPoolPositionsProps, PoolServiceCallResult, PoolSimulation, RemoveLiquidityProps, SimulatePoolOperationProps, WithdrawalMetadata } from "./types.js";
@@ -55,6 +56,10 @@ declare class PoolService extends SDKConstruct implements IPoolsService {
55
56
  * {@inheritDoc IPoolsService.listPositions}
56
57
  */
57
58
  listPositions(props: ListPoolPositionsProps): Promise<PoolPosition[]>;
59
+ /**
60
+ * {@inheritDoc IPoolsService.withdrawableLiquidity}
61
+ */
62
+ withdrawableLiquidity(pool: Address): Amount;
58
63
  }
59
64
  //#endregion
60
65
  export { PoolService };
@@ -147,8 +147,7 @@ interface PoolSimulation {
147
147
  **/
148
148
  zapper?: Address;
149
149
  /**
150
- * Withdrawals only: underlying the pool can actually hand over right now,
151
- * trimmed slightly so a withdrawal sized against it does not fail on rounding.
150
+ * Withdrawals only: {@link IPoolsService.withdrawableLiquidity}.
152
151
  *
153
152
  * The conversion is a rate, not a promise that the pool is liquid enough, so
154
153
  * compare `tokenOut.value` against `availableLiquidity.value` to see if the
@@ -265,6 +264,14 @@ interface IPoolsService {
265
264
  * several routes exist.
266
265
  **/
267
266
  simulateRedeem(props: SimulatePoolOperationProps): PoolSimulation;
267
+ /**
268
+ * The most the pool can hand over right now, trimmed so a share-sized
269
+ * withdrawal (redeem, zapper) survives the share price accruing before it is
270
+ * sent.
271
+ *
272
+ * @param pool - Pool address
273
+ **/
274
+ withdrawableLiquidity(pool: Address): Amount;
268
275
  /**
269
276
  * Returns contract call parameters for adding liquidity to a pool
270
277
  * Or undefined if no deposit action is required (e.g. for RWA underlying on demand)
@@ -19,13 +19,7 @@ interface PoolOperationArgs {
19
19
  */
20
20
  tokenOut: TokenAmount;
21
21
  }
22
- /**
23
- * What the pool's own state stops, whichever side of it the wallet is on.
24
- *
25
- * The liquidity read is the market's rather than the trimmed figure a
26
- * simulation carries: a withdrawal sized against that figure has to pass the
27
- * check that follows it.
28
- */
22
+ /** What the pool's own state stops, whichever side of it the wallet is on. */
29
23
  declare function checkPoolOperation(args: PoolOperationArgs): PoolOperationError[];
30
24
  //#endregion
31
25
  export { PoolOperationArgs, PoolOperationError, checkPoolOperation };
@@ -7,14 +7,7 @@ interface PoolLiquidityArgs {
7
7
  available: bigint;
8
8
  underlying: Token;
9
9
  }
10
- /**
11
- * What the pool holds, against what is being taken out of it.
12
- *
13
- * The operator is not `checkBorrowLimit`'s: a pool holding exactly the amount
14
- * requested still cannot serve it, so equality is already a refusal. That is
15
- * the rule the legacy withdrawal validator enforced and it is preserved to the
16
- * unit.
17
- */
10
+ /** What the pool can hand over, against what is being taken out of it. */
18
11
  declare function checkPoolLiquidity(args: PoolLiquidityArgs): InsufficientPoolLiquidityError[];
19
12
  //#endregion
20
13
  export { PoolLiquidityArgs, checkPoolLiquidity };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "17.0.0",
3
+ "version": "17.1.0-next.2",
4
4
  "description": "Gearbox SDK",
5
5
  "license": "MIT",
6
6
  "repository": {