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

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.
@@ -25,19 +25,27 @@ function proportionalDebt(position, collateralDelta) {
25
25
  return position.debt * collateralDelta / position.collateral;
26
26
  }
27
27
  /**
28
+ * Headroom on top of the debt read, in `PERCENTAGE_FACTOR`: enough interest for
29
+ * the transaction to sit in the mempool for hours at any sane borrow rate,
30
+ * small enough not to matter to the wallet that fronts it.
31
+ */
32
+ const SETTLE_MARGIN = 10n;
33
+ /**
28
34
  * Largest withdrawal (in underlying) that {@link proportionalDebt} can still
29
- * pay for: the repayment it implies leaves debt at or above `minDebt`, and
35
+ * pay for: the repayment it implies leaves debt at or above `minDebt` plus
36
+ * {@link SETTLE_MARGIN} of the debt, so the figure survives the interest of the
37
+ * blocks before it is sent, and
30
38
  * strictly less than the collateral goes — the last unit closes the account
31
39
  * rather than shrinks it. `0n` when the debt already sits below `minDebt`.
32
40
  *
33
- * Solves `floor(D0 · W / C0) ≤ D0 − minDebt` for `W`.
41
+ * Solves `floor(D0 · W / C0) ≤ D0 − minDebt − margin` for `W`.
34
42
  */
35
43
  function maxProportionalWithdrawal(position, debtLimits) {
36
44
  const { debt, collateral } = position;
37
45
  if (collateral <= 0n) return 0n;
38
46
  const allButLast = collateral - 1n;
39
47
  if (debt === 0n) return allButLast;
40
- const repayable = debt - debtLimits.minDebt;
48
+ const repayable = debt - debtLimits.minDebt - debt * SETTLE_MARGIN / require_onchain_constants_math.PERCENTAGE_FACTOR;
41
49
  if (repayable < 0n) return 0n;
42
50
  const bound = require_onchain_utils_bigint_math.BigIntMath.ceilDiv(collateral * (repayable + 1n), debt) - 1n;
43
51
  return bound < allButLast ? bound : allButLast;
@@ -63,6 +71,7 @@ function assertDebtLimits(sdk, debt, debtLimits, underlying) {
63
71
  }), debt > debtLimits.maxDebt ? `debt ${debt} exceeds maxDebt ${debtLimits.maxDebt}` : `debt ${debt} is below minDebt ${debtLimits.minDebt}`);
64
72
  }
65
73
  //#endregion
74
+ exports.SETTLE_MARGIN = SETTLE_MARGIN;
66
75
  exports.assertDebtLimits = assertDebtLimits;
67
76
  exports.assertLeverageAtLeastOne = assertLeverageAtLeastOne;
68
77
  exports.debtForLeverage = debtForLeverage;
@@ -361,14 +361,7 @@ const claim = (claimable) => ({
361
361
  claimable
362
362
  });
363
363
  const clearQuotas = () => ({ kind: "clearQuotas" });
364
- /**
365
- * Headroom a settlement raises on top of the debt it read, in
366
- * `PERCENTAGE_FACTOR`: enough interest for the transaction to sit in the
367
- * mempool for hours at any sane borrow rate, small enough not to matter to the
368
- * wallet that fronts it.
369
- */
370
- const SETTLE_MARGIN = 10n;
371
- const withMargin = (debt) => debt + debt * SETTLE_MARGIN / require_onchain_constants_math.PERCENTAGE_FACTOR;
364
+ const withMargin = (debt) => debt + debt * require_onchain_accounts_intents_math.SETTLE_MARGIN / require_onchain_constants_math.PERCENTAGE_FACTOR;
372
365
  /** The amount that asks for all of it, whatever "all" turns out to be. */
373
366
  const everything = (amount) => amount >= require_onchain_constants_math.MAX_UINT256;
374
367
  const min = (a, b) => a < b ? a : b;
@@ -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";
@@ -24,19 +24,27 @@ function proportionalDebt(position, collateralDelta) {
24
24
  return position.debt * collateralDelta / position.collateral;
25
25
  }
26
26
  /**
27
+ * Headroom on top of the debt read, in `PERCENTAGE_FACTOR`: enough interest for
28
+ * the transaction to sit in the mempool for hours at any sane borrow rate,
29
+ * small enough not to matter to the wallet that fronts it.
30
+ */
31
+ const SETTLE_MARGIN = 10n;
32
+ /**
27
33
  * Largest withdrawal (in underlying) that {@link proportionalDebt} can still
28
- * pay for: the repayment it implies leaves debt at or above `minDebt`, and
34
+ * pay for: the repayment it implies leaves debt at or above `minDebt` plus
35
+ * {@link SETTLE_MARGIN} of the debt, so the figure survives the interest of the
36
+ * blocks before it is sent, and
29
37
  * strictly less than the collateral goes — the last unit closes the account
30
38
  * rather than shrinks it. `0n` when the debt already sits below `minDebt`.
31
39
  *
32
- * Solves `floor(D0 · W / C0) ≤ D0 − minDebt` for `W`.
40
+ * Solves `floor(D0 · W / C0) ≤ D0 − minDebt − margin` for `W`.
33
41
  */
34
42
  function maxProportionalWithdrawal(position, debtLimits) {
35
43
  const { debt, collateral } = position;
36
44
  if (collateral <= 0n) return 0n;
37
45
  const allButLast = collateral - 1n;
38
46
  if (debt === 0n) return allButLast;
39
- const repayable = debt - debtLimits.minDebt;
47
+ const repayable = debt - debtLimits.minDebt - debt * SETTLE_MARGIN / PERCENTAGE_FACTOR;
40
48
  if (repayable < 0n) return 0n;
41
49
  const bound = BigIntMath.ceilDiv(collateral * (repayable + 1n), debt) - 1n;
42
50
  return bound < allButLast ? bound : allButLast;
@@ -62,4 +70,4 @@ function assertDebtLimits(sdk, debt, debtLimits, underlying) {
62
70
  }), debt > debtLimits.maxDebt ? `debt ${debt} exceeds maxDebt ${debtLimits.maxDebt}` : `debt ${debt} is below minDebt ${debtLimits.minDebt}`);
63
71
  }
64
72
  //#endregion
65
- export { assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, maxProportionalWithdrawal, proportionalDebt };
73
+ export { SETTLE_MARGIN, assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, maxProportionalWithdrawal, proportionalDebt };
@@ -6,7 +6,7 @@ import "../../../model/index.js";
6
6
  import { toToken, toTokenAmount } from "../../validation/helpers/token.js";
7
7
  import { IntentPreviewError } from "../../validation/raise.js";
8
8
  import { eq } from "./utils/common.js";
9
- import { assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, proportionalDebt } from "./math.js";
9
+ import { SETTLE_MARGIN, assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, proportionalDebt } from "./math.js";
10
10
  //#region src/onchain/accounts/intents/plan.ts
11
11
  /** Whatever the previous convert produced. */
12
12
  const RAISED = { raised: true };
@@ -360,13 +360,6 @@ const claim = (claimable) => ({
360
360
  claimable
361
361
  });
362
362
  const clearQuotas = () => ({ kind: "clearQuotas" });
363
- /**
364
- * Headroom a settlement raises on top of the debt it read, in
365
- * `PERCENTAGE_FACTOR`: enough interest for the transaction to sit in the
366
- * mempool for hours at any sane borrow rate, small enough not to matter to the
367
- * wallet that fronts it.
368
- */
369
- const SETTLE_MARGIN = 10n;
370
363
  const withMargin = (debt) => debt + debt * SETTLE_MARGIN / PERCENTAGE_FACTOR;
371
364
  /** The amount that asks for all of it, whatever "all" turns out to be. */
372
365
  const everything = (amount) => amount >= MAX_UINT256;
@@ -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),
@@ -28,13 +28,21 @@ declare function debtForLeverage(collateral: bigint, leverage: bigint): bigint;
28
28
  * it, so no rounding is introduced on the way.
29
29
  */
30
30
  declare function proportionalDebt(position: Position, collateralDelta: bigint): bigint;
31
+ /**
32
+ * Headroom on top of the debt read, in `PERCENTAGE_FACTOR`: enough interest for
33
+ * the transaction to sit in the mempool for hours at any sane borrow rate,
34
+ * small enough not to matter to the wallet that fronts it.
35
+ */
36
+ declare const SETTLE_MARGIN = 10n;
31
37
  /**
32
38
  * Largest withdrawal (in underlying) that {@link proportionalDebt} can still
33
- * pay for: the repayment it implies leaves debt at or above `minDebt`, and
39
+ * pay for: the repayment it implies leaves debt at or above `minDebt` plus
40
+ * {@link SETTLE_MARGIN} of the debt, so the figure survives the interest of the
41
+ * blocks before it is sent, and
34
42
  * strictly less than the collateral goes — the last unit closes the account
35
43
  * rather than shrinks it. `0n` when the debt already sits below `minDebt`.
36
44
  *
37
- * Solves `floor(D0 · W / C0) ≤ D0 − minDebt` for `W`.
45
+ * Solves `floor(D0 · W / C0) ≤ D0 − minDebt − margin` for `W`.
38
46
  */
39
47
  declare function maxProportionalWithdrawal(position: Position, debtLimits: DebtLimits): bigint;
40
48
  /** Total leverage cannot drop below 1x — that would be negative debt. */
@@ -45,4 +53,4 @@ declare function assertLeverageAtLeastOne(leverage: bigint): void;
45
53
  */
46
54
  declare function assertDebtLimits(sdk: OnchainSDK, debt: bigint, debtLimits: DebtLimits, underlying: Address): void;
47
55
  //#endregion
48
- export { DebtLimits, Position, assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, maxProportionalWithdrawal, proportionalDebt };
56
+ export { DebtLimits, Position, SETTLE_MARGIN, assertDebtLimits, assertLeverageAtLeastOne, debtForLeverage, maxProportionalWithdrawal, proportionalDebt };
@@ -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.1",
4
4
  "description": "Gearbox SDK",
5
5
  "license": "MIT",
6
6
  "repository": {