@gearbox-protocol/sdk 16.3.2 → 16.4.0-next.10

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.
Files changed (139) hide show
  1. package/dist/cjs/dev/index.js +3 -2
  2. package/dist/cjs/dev/kycUtils.js +18 -35
  3. package/dist/cjs/dev/midasUtils.js +40 -11
  4. package/dist/cjs/dev/securitizeUtils.js +14 -10
  5. package/dist/cjs/dev/withdrawalUtils.js +3 -6
  6. package/dist/cjs/model/errors/index.js +2 -0
  7. package/dist/cjs/model/errors/operation-errors.js +18 -0
  8. package/dist/cjs/model/index.js +2 -0
  9. package/dist/cjs/onchain/accounts/CreditAccountsServiceV310.js +0 -1
  10. package/dist/cjs/onchain/accounts/intents/borrow.js +139 -0
  11. package/dist/cjs/onchain/accounts/intents/collateral-valuation.js +41 -0
  12. package/dist/cjs/onchain/accounts/intents/guards.js +15 -3
  13. package/dist/cjs/onchain/accounts/intents/index.js +107 -20
  14. package/dist/cjs/onchain/accounts/intents/leverage-band.js +2 -12
  15. package/dist/cjs/onchain/accounts/intents/maxBorrow.js +89 -0
  16. package/dist/cjs/onchain/accounts/intents/maxWithdrawCollateral.js +15 -41
  17. package/dist/cjs/onchain/accounts/intents/open-strategy.js +6 -45
  18. package/dist/cjs/onchain/accounts/intents/realize.js +54 -2
  19. package/dist/cjs/onchain/accounts/intents/tail.js +1 -1
  20. package/dist/cjs/onchain/accounts/intents/testing/sdk-mock.js +1 -0
  21. package/dist/cjs/onchain/accounts/intents/utils/common.js +19 -0
  22. package/dist/cjs/onchain/accounts/intents/utils/credit-account-slice.js +21 -0
  23. package/dist/cjs/onchain/accounts/intents/utils/index.js +2 -0
  24. package/dist/cjs/onchain/accounts/intents/utils/price-impact.js +3 -3
  25. package/dist/cjs/onchain/accounts/intents/withdraw-limits.js +97 -0
  26. package/dist/cjs/onchain/core/createAddressProvider.js +2 -5
  27. package/dist/cjs/onchain/index.js +6 -0
  28. package/dist/cjs/onchain/market/adapters/abi/conctructorAbi.js +1 -1
  29. package/dist/cjs/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +11 -3
  30. package/dist/cjs/onchain/positions/calcHealthFactor.js +3 -3
  31. package/dist/cjs/onchain/preview/index.js +2 -0
  32. package/dist/cjs/onchain/preview/preview/index.js +2 -0
  33. package/dist/cjs/onchain/preview/preview/midasGreenlistsAccount.js +17 -0
  34. package/dist/cjs/onchain/preview/preview/previewOpenStrategyPosition.js +13 -16
  35. package/dist/cjs/onchain/preview/preview/previewOperation.js +19 -11
  36. package/dist/cjs/onchain/preview/preview/replayMulticall.js +4 -3
  37. package/dist/cjs/onchain/validation/bundles/checkCollateralFunding.js +3 -3
  38. package/dist/cjs/onchain/validation/bundles/checkCreditOperation.js +4 -3
  39. package/dist/cjs/onchain/validation/bundles/checkMidasAccountGreenlist.js +44 -0
  40. package/dist/cjs/onchain/validation/bundles/checkRWAOpening.js +16 -7
  41. package/dist/cjs/onchain/validation/bundles/index.js +2 -0
  42. package/dist/cjs/onchain/validation/checkOperation.js +0 -1
  43. package/dist/cjs/onchain/validation/checks/checkReservePriceLimited.js +30 -0
  44. package/dist/cjs/onchain/validation/checks/index.js +2 -0
  45. package/dist/cjs/onchain/validation/index.js +4 -0
  46. package/dist/cjs/sdk/execute/ExecuteApi.js +65 -5
  47. package/dist/cjs/sdk/prepare/PrepareApi.js +89 -14
  48. package/dist/esm/dev/index.js +3 -3
  49. package/dist/esm/dev/kycUtils.js +17 -33
  50. package/dist/esm/dev/midasUtils.js +39 -12
  51. package/dist/esm/dev/securitizeUtils.js +15 -11
  52. package/dist/esm/dev/withdrawalUtils.js +3 -6
  53. package/dist/esm/model/errors/index.js +2 -2
  54. package/dist/esm/model/errors/operation-errors.js +17 -1
  55. package/dist/esm/model/index.js +2 -2
  56. package/dist/esm/onchain/accounts/CreditAccountsServiceV310.js +0 -1
  57. package/dist/esm/onchain/accounts/intents/borrow.js +137 -0
  58. package/dist/esm/onchain/accounts/intents/collateral-valuation.js +40 -0
  59. package/dist/esm/onchain/accounts/intents/guards.js +15 -3
  60. package/dist/esm/onchain/accounts/intents/index.js +107 -20
  61. package/dist/esm/onchain/accounts/intents/leverage-band.js +2 -12
  62. package/dist/esm/onchain/accounts/intents/maxBorrow.js +87 -0
  63. package/dist/esm/onchain/accounts/intents/maxWithdrawCollateral.js +15 -41
  64. package/dist/esm/onchain/accounts/intents/open-strategy.js +6 -45
  65. package/dist/esm/onchain/accounts/intents/realize.js +54 -2
  66. package/dist/esm/onchain/accounts/intents/tail.js +1 -1
  67. package/dist/esm/onchain/accounts/intents/testing/sdk-mock.js +1 -0
  68. package/dist/esm/onchain/accounts/intents/utils/common.js +19 -1
  69. package/dist/esm/onchain/accounts/intents/utils/credit-account-slice.js +21 -1
  70. package/dist/esm/onchain/accounts/intents/utils/index.js +3 -3
  71. package/dist/esm/onchain/accounts/intents/utils/price-impact.js +3 -3
  72. package/dist/esm/onchain/accounts/intents/withdraw-limits.js +95 -0
  73. package/dist/esm/onchain/core/createAddressProvider.js +2 -5
  74. package/dist/esm/onchain/index.js +4 -1
  75. package/dist/esm/onchain/market/adapters/abi/conctructorAbi.js +1 -1
  76. package/dist/esm/onchain/market/adapters/contracts/MidasGatewayAdapterContract.js +11 -3
  77. package/dist/esm/onchain/positions/calcHealthFactor.js +3 -3
  78. package/dist/esm/onchain/preview/index.js +2 -1
  79. package/dist/esm/onchain/preview/preview/index.js +2 -1
  80. package/dist/esm/onchain/preview/preview/midasGreenlistsAccount.js +16 -0
  81. package/dist/esm/onchain/preview/preview/previewOpenStrategyPosition.js +14 -17
  82. package/dist/esm/onchain/preview/preview/previewOperation.js +19 -11
  83. package/dist/esm/onchain/preview/preview/replayMulticall.js +4 -3
  84. package/dist/esm/onchain/validation/bundles/checkCollateralFunding.js +3 -3
  85. package/dist/esm/onchain/validation/bundles/checkCreditOperation.js +4 -3
  86. package/dist/esm/onchain/validation/bundles/checkMidasAccountGreenlist.js +43 -0
  87. package/dist/esm/onchain/validation/bundles/checkRWAOpening.js +16 -7
  88. package/dist/esm/onchain/validation/bundles/index.js +2 -1
  89. package/dist/esm/onchain/validation/checkOperation.js +0 -1
  90. package/dist/esm/onchain/validation/checks/checkReservePriceLimited.js +29 -0
  91. package/dist/esm/onchain/validation/checks/index.js +2 -1
  92. package/dist/esm/onchain/validation/index.js +3 -1
  93. package/dist/esm/sdk/execute/ExecuteApi.js +65 -5
  94. package/dist/esm/sdk/prepare/PrepareApi.js +89 -14
  95. package/dist/types/dev/index.d.ts +3 -3
  96. package/dist/types/dev/kycUtils.d.ts +1 -5
  97. package/dist/types/dev/midasUtils.d.ts +11 -1
  98. package/dist/types/model/errors/index.d.ts +2 -2
  99. package/dist/types/model/errors/operation-errors.d.ts +54 -1
  100. package/dist/types/model/index.d.ts +3 -3
  101. package/dist/types/model/previews.d.ts +25 -19
  102. package/dist/types/onchain/accounts/index.d.ts +4 -3
  103. package/dist/types/onchain/accounts/intents/borrow.d.ts +141 -0
  104. package/dist/types/onchain/accounts/intents/collateral-valuation.d.ts +42 -0
  105. package/dist/types/onchain/accounts/intents/guards.d.ts +18 -2
  106. package/dist/types/onchain/accounts/intents/index.d.ts +102 -14
  107. package/dist/types/onchain/accounts/intents/maxBorrow.d.ts +54 -0
  108. package/dist/types/onchain/accounts/intents/maxWithdrawCollateral.d.ts +3 -8
  109. package/dist/types/onchain/accounts/intents/open-strategy.d.ts +3 -17
  110. package/dist/types/onchain/accounts/intents/testing/sdk-mock.d.ts +2 -0
  111. package/dist/types/onchain/accounts/intents/tests/open-strategy.fixtures.d.ts +2 -2
  112. package/dist/types/onchain/accounts/intents/types.d.ts +41 -5
  113. package/dist/types/onchain/accounts/intents/utils/common.d.ts +15 -1
  114. package/dist/types/onchain/accounts/intents/utils/credit-account-slice.d.ts +14 -1
  115. package/dist/types/onchain/accounts/intents/utils/index.d.ts +3 -3
  116. package/dist/types/onchain/accounts/intents/withdraw-limits.d.ts +80 -0
  117. package/dist/types/onchain/index.d.ts +8 -4
  118. package/dist/types/onchain/market/adapters/contracts/MidasGatewayAdapterContract.d.ts +8 -2
  119. package/dist/types/onchain/preview/index.d.ts +2 -1
  120. package/dist/types/onchain/preview/preview/index.d.ts +2 -1
  121. package/dist/types/onchain/preview/preview/midasGreenlistsAccount.d.ts +13 -0
  122. package/dist/types/onchain/preview/preview/previewOpenStrategyPosition.d.ts +5 -3
  123. package/dist/types/onchain/preview/preview/replayMulticall.d.ts +8 -7
  124. package/dist/types/onchain/validation/bundles/checkCreditOperation.d.ts +2 -2
  125. package/dist/types/onchain/validation/bundles/checkMidasAccountGreenlist.d.ts +22 -0
  126. package/dist/types/onchain/validation/bundles/checkRWAOpening.d.ts +6 -4
  127. package/dist/types/onchain/validation/bundles/index.d.ts +3 -2
  128. package/dist/types/onchain/validation/checks/checkDebtLimits.d.ts +2 -2
  129. package/dist/types/onchain/validation/checks/checkReservePriceLimited.d.ts +31 -0
  130. package/dist/types/onchain/validation/checks/index.d.ts +2 -1
  131. package/dist/types/onchain/validation/index.d.ts +4 -2
  132. package/dist/types/onchain/validation/raise.d.ts +2 -2
  133. package/dist/types/sdk/execute/index.d.ts +2 -2
  134. package/dist/types/sdk/execute/types.d.ts +48 -6
  135. package/dist/types/sdk/index.d.ts +5 -4
  136. package/dist/types/sdk/prepare/PrepareApi.d.ts +16 -4
  137. package/dist/types/sdk/prepare/index.d.ts +4 -3
  138. package/dist/types/sdk/prepare/types.d.ts +199 -65
  139. package/package.json +1 -1
@@ -0,0 +1,42 @@
1
+ import { OnchainSDK } from "../../OnchainSDK.js";
2
+ import { CreditAccountSlice } from "./types.js";
3
+ import "../../index.js";
4
+ import { Address } from "viem";
5
+ //#region src/onchain/accounts/intents/collateral-valuation.d.ts
6
+ /** One balance on the account, as the slice carries it. */
7
+ type Holding = CreditAccountSlice["tokens"][number];
8
+ /**
9
+ * The collateral check's own valuation of an account, as a handful of lookups.
10
+ *
11
+ * Shared by everything that solves that check for an amount, so the rules it
12
+ * encodes are written once: a holding backed by a quota counts the lesser of the
13
+ * quota and its threshold-weighted value, an unquoted one its weighted value
14
+ * alone, and dust or a disabled balance nothing at all. Collateral is valued at
15
+ * the protocol safe price — `min` of the two feeds, 0 where there is no reserve
16
+ * — the way the facade values a call that hands funds over; the underlying is
17
+ * exempt and stays on the main feed, as `CreditManagerV3._safeConvertToUSD`
18
+ * does.
19
+ *
20
+ * Every figure is carried in USD × `PERCENTAGE_FACTOR`, the units the check
21
+ * compares in, so a threshold never has to be divided back out.
22
+ */
23
+ interface CollateralValuation {
24
+ /** Market underlying, the one token safe pricing does not touch. */
25
+ underlying: Address;
26
+ /** Whether the holding is weighed at all. */
27
+ counts(holding: Holding): boolean;
28
+ /** What the holding backs, in USD × `PERCENTAGE_FACTOR`. */
29
+ weigh(holding: Holding): bigint;
30
+ /** What the holding's quota backs, in the same units; 0 on a closed market. */
31
+ quotaValue(holding: Holding): bigint;
32
+ /** USD at the main feed; `undefined` when the token has no price at all. */
33
+ mainUsd(token: Address, amount: bigint): bigint | undefined;
34
+ /** USD the check counts the holding at, before its threshold. */
35
+ checkedUsd(holding: Holding): bigint;
36
+ /** Liquidation threshold in basis points; 0 for a token the manager refuses. */
37
+ lt(token: Address): bigint;
38
+ }
39
+ /** {@inheritDoc CollateralValuation} */
40
+ declare function collateralValuation(creditAccount: CreditAccountSlice, sdk: OnchainSDK): CollateralValuation;
41
+ //#endregion
42
+ export { CollateralValuation, Holding, collateralValuation };
@@ -1,3 +1,5 @@
1
+ import { Bps, TokenAmount } from "../../../model/primitives.js";
2
+ import "../../../model/index.js";
1
3
  import { Asset } from "../../base/types.js";
2
4
  import { MarketSuite } from "../../market/MarketSuite.js";
3
5
  import { CreditSuite } from "../../market/credit/CreditSuite.js";
@@ -74,11 +76,25 @@ declare function assertGrowthAllowed(args: {
74
76
  * whose reserve feed the SDK cannot read keeps its main price, so a plan can
75
77
  * still be refused on-chain after passing here.
76
78
  */
77
- declare function assertCollateralised(healthFactorBps: number, safePrices: boolean): void;
79
+ declare function assertCollateralised(healthFactorBps: number, safePrices: boolean, atSafePrices?: SafePriceEvidence): void;
80
+ /**
81
+ * What tells a reserve feed marking collateral down apart from a position that
82
+ * is simply too small, read only when the collateral check has already failed.
83
+ *
84
+ * A thunk because both halves are expensive: the account has to be valued a
85
+ * second time at the main feed, and the check solved for the amount that would
86
+ * still clear it.
87
+ */
88
+ type SafePriceEvidence = () => {
89
+ /** The plan's end state weighed at the main feed. */
90
+ atMainPrices: Bps;
91
+ /** What the account can still take out, in the market's underlying. */
92
+ withdrawable: TokenAmount;
93
+ };
78
94
  /**
79
95
  * A quota can only be raised as far as the market still has room for: past the
80
96
  * token's limit the keeper takes nothing more, whoever is asking.
81
97
  */
82
98
  declare function assertQuotaAvailable(sdk: OnchainSDK, market: MarketSuite, increases: readonly Asset[]): void;
83
99
  //#endregion
84
- export { assertCanBorrow, assertCollateralised, assertGrowthAllowed, assertMarketOperable, assertQuotaAvailable };
100
+ export { SafePriceEvidence, assertCanBorrow, assertCollateralised, assertGrowthAllowed, assertMarketOperable, assertQuotaAvailable };
@@ -2,9 +2,11 @@ import { SDKError } from "../../../model/result.js";
2
2
  import "../../../model/index.js";
3
3
  import { SDKConstruct } from "../../base/SDKConstruct.js";
4
4
  import { IntentValidationError } from "../../validation/raise.js";
5
- import { LeverageBand, LeverageBandProps } from "./leverage-band.js";
6
5
  import { AccountCalculatorOperation } from "./operations.js";
7
6
  import { AddCollateralIntent, AdjustLeverageIntent, ClaimRemainder, CreditAccountSlice, DelayableIntent, DelayedRoute, DelayedStart, DelayedStartResult, DepositStrategyIntent, FinishIntentProps, FinishIntentResult, InstantRoute, IntentPreviewResult, IntentRoutesResult, OperationState, PathLossRate, RepayStrategyIntent, ResumableIntent, RouteErrors, StartIntent, StartIntentProps, WithdrawAssetIntent, WithdrawCeilings, WithdrawStrategyIntent } from "./types.js";
7
+ import { BorrowProps, BorrowState } from "./borrow.js";
8
+ import { LeverageBand, LeverageBandProps } from "./leverage-band.js";
9
+ import { MaxBorrowProps } from "./maxBorrow.js";
8
10
  import { OpenStrategyProps, OpenStrategyState } from "./open-strategy.js";
9
11
  import { fetchCreditAccountSlice, toCreditAccountSlice } from "./utils/credit-account-slice.js";
10
12
  import { isPhantomToken } from "./utils/pick-token.js";
@@ -21,6 +23,22 @@ type OpenStrategyPreviewResult = {
21
23
  ok: true;
22
24
  state: OpenStrategyState;
23
25
  } | SDKError<IntentValidationError>;
26
+ /**
27
+ * Borrow preview outcome, shaped like {@link OpenStrategyPreviewResult}: both
28
+ * open an account, so neither has an operation chain to report.
29
+ */
30
+ type BorrowPreviewResult = {
31
+ ok: true;
32
+ state: BorrowState;
33
+ } | SDKError<IntentValidationError>;
34
+ /**
35
+ * Empty-account preview outcome: the thinnest of the three, since an account
36
+ * that holds nothing has no state to project — only the market's own refusal
37
+ * to open one at all.
38
+ */
39
+ type EmptyAccountPreviewResult = {
40
+ ok: true;
41
+ } | SDKError<IntentValidationError>;
24
42
  /** An intent plus everything previewing it needs. */
25
43
  type StartProps = StartIntentProps & {
26
44
  intent: StartIntent;
@@ -45,21 +63,30 @@ declare class CreditAccountOperationsService extends SDKConstruct {
45
63
  startIntent(props: StartProps): Promise<IntentPreviewResult>;
46
64
  /**
47
65
  * Both ends of what a `WITHDRAW` can take out, in underlying: the largest
48
- * partial withdrawal that keeps leverage and stays inside the facade's
49
- * `debtLimits`, and the net value an exit hands over. They are reported together
50
- * because a withdraw form needs both — the range it may offer, and the one
51
- * amount past it that is allowed — and because the distance between them is
52
- * the account's own, not a constant a caller could assume.
66
+ * partial withdrawal that keeps leverage, and the net value an exit hands
67
+ * over. They are reported together because a withdraw form needs both — the
68
+ * range it may offer, and the one amount past it that is allowed — and
69
+ * because the distance between them is the account's own, not a constant a
70
+ * caller could assume.
53
71
  *
54
- * Takes no target health factor, unlike {@link maxWithdrawCollateral}: a
55
- * proportional withdrawal leaves the factor where it found it, and the
56
- * facade's `minDebt` is what bounds it.
72
+ * Two rules bound the partial end and both are reported: the facade's
73
+ * `debtLimits` as `partial`, and the safe-price collateral check on top of
74
+ * it as `safePartial`. The second is the one to offer — see
75
+ * {@link WithdrawCeilings}.
57
76
  *
58
- * @param props - Account slice and the SDK holding its market
59
- * @returns The two ceilings, see {@link WithdrawCeilings} for the gap between
60
- * them
77
+ * Takes no target health factor, unlike {@link maxWithdrawCollateral}. A
78
+ * proportional withdrawal leaves the factor where it found it, so there is
79
+ * no room to choose: what these answer to is the facade's own threshold,
80
+ * which is also what {@link startIntent} refuses against.
81
+ *
82
+ * @param props - Account slice, the SDK holding its market, and optionally
83
+ * the collateral the withdrawal would be funded from
84
+ * @returns The three limits, see {@link WithdrawCeilings} for the gap
85
+ * between them
61
86
  */
62
- maxWithdraw(props: Pick<StartIntentProps, "creditAccount" | "sdk">): WithdrawCeilings;
87
+ maxWithdraw(props: Pick<StartIntentProps, "creditAccount" | "sdk"> & {
88
+ sourceToken?: Address;
89
+ }): WithdrawCeilings;
63
90
  /**
64
91
  * Debt a `REPAY` would have to cover to settle the account, in underlying
65
92
  * units: principal plus the interest and fees accrued as of the read.
@@ -110,6 +137,30 @@ declare class CreditAccountOperationsService extends SDKConstruct {
110
137
  token: Address;
111
138
  targetHF?: bigint;
112
139
  }): bigint;
140
+ /**
141
+ * Largest loan a given collateral supports at `targetHF`, in the payout
142
+ * token's units — the ceiling a borrow form should offer.
143
+ *
144
+ * Reads no account, like {@link leverageBand}: the borrow opens one. The
145
+ * collateral is valued the way the transaction will be judged, at safe
146
+ * prices and under the quota the borrow buys, and the answer is then held to
147
+ * what the market will lend.
148
+ *
149
+ * A ceiling, not a verdict: the facade's `minDebt` is a floor and is not
150
+ * applied here, so collateral too small for this market still answers with
151
+ * what it carries and {@link borrowIntent} is the one that refuses the loan.
152
+ *
153
+ * The default is {@link MIN_HF_LIMITED}, the threshold a form holds an
154
+ * account to.
155
+ *
156
+ * @param props - The manager, the SDK holding its market, the collateral put
157
+ * up, the token to be paid in, and optionally the health factor to land at
158
+ * @returns Amount in the payout token's units; `0n` where no loan of this
159
+ * shape can be funded at any size
160
+ */
161
+ maxBorrow(props: Omit<MaxBorrowProps, "targetHF"> & {
162
+ targetHF?: bigint;
163
+ }): bigint;
113
164
  /**
114
165
  * Previews the same operation when its source only redeems through its
115
166
  * issuer: a Securitize dsToken, a Mellow share.
@@ -177,6 +228,21 @@ declare class CreditAccountOperationsService extends SDKConstruct {
177
228
  * beside it, so both halves of an operation are consumed the same way
178
229
  */
179
230
  finishIntent(props: FinishIntentProps): Promise<FinishIntentResult>;
231
+ /**
232
+ * Previews opening an account that holds nothing.
233
+ *
234
+ * Nothing is put up, drawn or routed, so there is no state to build and no
235
+ * guard to run beyond the market's own: a paused or expired facade takes no
236
+ * multicall, and an opening is a multicall like any other. Answers the same
237
+ * envelope its two neighbours do so a caller branches on `ok` throughout.
238
+ *
239
+ * @param props - The SDK holding the market, and the manager to open in
240
+ * @returns `{ ok: true }`, or `{ ok: false, error }` when the market takes
241
+ * no transaction right now
242
+ */
243
+ openEmptyAccountIntent(props: Pick<StartIntentProps, "sdk"> & {
244
+ creditManager: Address;
245
+ }): Promise<EmptyAccountPreviewResult>;
180
246
  /**
181
247
  * Previews opening a brand-new leveraged position.
182
248
  *
@@ -190,6 +256,28 @@ declare class CreditAccountOperationsService extends SDKConstruct {
190
256
  * leverage or the resulting debt is not viable
191
257
  */
192
258
  openStrategyIntent(props: OpenStrategyProps): Promise<OpenStrategyPreviewResult>;
259
+ /**
260
+ * Previews taking a loan against collateral, on an account this same
261
+ * transaction opens.
262
+ *
263
+ * Sits beside {@link openStrategyIntent} rather than under
264
+ * {@link startIntent} for the same reason: there is no account yet, and the
265
+ * output feeds `sdk.accounts.openCA`. What sets it apart from an opening is
266
+ * where the loan goes — out to the wallet rather than into a position — so
267
+ * the debt is named outright instead of following from a leverage, and the
268
+ * collateral is the only thing the account is left holding.
269
+ *
270
+ * `creditAccount` draws the loan on one the wallet already holds instead of
271
+ * opening another, as an opening takes one.
272
+ *
273
+ * @param props - Credit manager, the collateral the wallet puts up and the
274
+ * payout it asks for
275
+ * @returns Debt, the payout's two branches and the projection the account
276
+ * lands in, or `{ ok: false, error }` when the loan is not viable — a debt
277
+ * outside the facade's limits, collateral that cannot carry it, a payout the
278
+ * router has no path to
279
+ */
280
+ borrowIntent(props: BorrowProps): Promise<BorrowPreviewResult>;
193
281
  }
194
282
  //#endregion
195
- export { type AccountCalculatorOperation, type AddCollateralIntent, type AdjustLeverageIntent, type ClaimRemainder, CreditAccountOperationsService, type CreditAccountSlice, type DelayableIntent, type DelayedRoute, type DelayedStart, type DelayedStartResult, type DepositStrategyIntent, type FinishIntentProps, type FinishIntentResult, type InstantRoute, type IntentPreviewResult, type IntentRoutesResult, type LeverageBand, OpenStrategyPreviewResult, type OpenStrategyProps, type OpenStrategyState, type OperationState, type PathLossRate, type RepayStrategyIntent, type ResumableIntent, type RouteErrors, type StartIntent, type WithdrawAssetIntent, type WithdrawCeilings, type WithdrawStrategyIntent, fetchCreditAccountSlice, isPhantomToken, toCreditAccountSlice };
283
+ export { type AccountCalculatorOperation, type AddCollateralIntent, type AdjustLeverageIntent, BorrowPreviewResult, type BorrowProps, type BorrowState, type ClaimRemainder, CreditAccountOperationsService, type CreditAccountSlice, type DelayableIntent, type DelayedRoute, type DelayedStart, type DelayedStartResult, type DepositStrategyIntent, EmptyAccountPreviewResult, type FinishIntentProps, type FinishIntentResult, type InstantRoute, type IntentPreviewResult, type IntentRoutesResult, type LeverageBand, OpenStrategyPreviewResult, type OpenStrategyProps, type OpenStrategyState, type OperationState, type PathLossRate, type RepayStrategyIntent, type ResumableIntent, type RouteErrors, type StartIntent, type WithdrawAssetIntent, type WithdrawCeilings, type WithdrawStrategyIntent, fetchCreditAccountSlice, isPhantomToken, toCreditAccountSlice };
@@ -0,0 +1,54 @@
1
+ import { OnchainSDK } from "../../OnchainSDK.js";
2
+ import "../../index.js";
3
+ import { Address } from "viem";
4
+ //#region src/onchain/accounts/intents/maxBorrow.d.ts
5
+ interface MaxBorrowProps {
6
+ sdk: OnchainSDK;
7
+ /** Credit manager the loan would be taken in. */
8
+ creditManager: Address;
9
+ /** Token the wallet puts up, in the manager's collateral list. */
10
+ collateralToken: Address;
11
+ /** Amount of {@link collateralToken}, in its own units. */
12
+ collateralAmount: bigint;
13
+ /** Token the loan is paid out in; the answer is in its units. */
14
+ borrowToken: Address;
15
+ /** Health factor the loan has to leave the account at, in basis points. */
16
+ targetHF: bigint;
17
+ /** Extra quota headroom in PERCENTAGE_FORMAT, as the borrow itself takes. */
18
+ quotaReserve: number | undefined;
19
+ }
20
+ /**
21
+ * Largest loan this collateral supports at `targetHF` — the ceiling a borrow
22
+ * form should offer, in the payout token's units.
23
+ *
24
+ * The inverse of a borrow rather than a search for one: the loan leaves the
25
+ * account entirely, so the collateral is the whole of what backs the debt, and
26
+ * the health factor is one division away from the amount. Solving it the other
27
+ * way round costs a division too, and no iteration.
28
+ *
29
+ * Collateral is valued the way the transaction will be judged — at safe
30
+ * prices, under its liquidation threshold, capped by the quota the borrow
31
+ * buys for it, all of which is {@link collateralValuation}'s business. The ceiling
32
+ * is then held to what the market will actually lend: the pool's free
33
+ * liquidity, the manager's own allowance and the facade's `maxDebt`, whichever
34
+ * binds first.
35
+ *
36
+ * The facade's `minDebt` is deliberately not applied. It is a floor, and a
37
+ * ceiling answered as `0n` because the collateral is too small for this market
38
+ * would tell a form nothing about what it is holding — the number a user needs
39
+ * to see is the one they are short of. Collateral that carries something
40
+ * therefore answers with it, whether or not the market would lend that little;
41
+ * a loan under the floor is refused by `borrow` itself, with `debtOutOfRange`
42
+ * naming both ends.
43
+ *
44
+ * Nothing is fetched or simulated — the account does not exist yet and every
45
+ * input is loaded market state, so a form can call this on each keystroke.
46
+ *
47
+ * @param props - {@link MaxBorrowProps}
48
+ * @returns Amount in the payout token's units; `0n` where no loan of this
49
+ * shape exists at any size — a collateral that backs nothing at safe prices, a
50
+ * market with nothing left to lend, and a manager the SDK does not hold yet
51
+ **/
52
+ declare function maxBorrow(props: MaxBorrowProps): bigint;
53
+ //#endregion
54
+ export { MaxBorrowProps, maxBorrow };
@@ -16,14 +16,9 @@ interface MaxWithdrawCollateralProps {
16
16
  * factor stays at or above `targetHF`.
17
17
  *
18
18
  * This is the collateral check solved for one balance, and it counts what that
19
- * check counts: a holding backed by a quota contributes the lesser of the
20
- * quota and its threshold-weighted value, an unquoted one — the underlying —
21
- * its weighted value alone, and dust or a disabled balance nothing at all.
22
- * Collateral is valued at the protocol safe price (`min` of the two feeds,
23
- * 0 when there is no reserve), the way the facade values a call that hands
24
- * funds over; the underlying is exempt and is valued at the main feed, as
25
- * `CreditManagerV3._safeConvertToUSD` does. The debt is valued at the main
26
- * feed, as the check does. Zero debt frees the whole balance.
19
+ * check counts — see {@link collateralValuation} for it, safe prices included.
20
+ * The debt is valued at the main feed, as the check does. Zero debt frees the
21
+ * whole balance.
27
22
  *
28
23
  * Rounding always favours the account, so the answer clears the check rather
29
24
  * than landing a wei short of it.
@@ -8,15 +8,8 @@ import { CreditAccountSlice, SimulationPrices } from "./types.js";
8
8
  import "../../index.js";
9
9
  import { Address } from "viem";
10
10
  //#region src/onchain/accounts/intents/open-strategy.d.ts
11
- /**
12
- * Opening an account and putting a position on it in one transaction.
13
- *
14
- * The union says which of the two openings this is: {@link OpenStrategyEmpty}
15
- * takes only the market, because an account holding nothing has nothing to
16
- * route, no leverage to reach and no target to reach it in.
17
- */
18
- type OpenStrategyProps = OpenStrategyFunded | OpenStrategyEmpty;
19
- interface OpenStrategyFunded {
11
+ /** Opening an account and putting a position on it in one transaction. */
12
+ interface OpenStrategyProps {
20
13
  sdk: OnchainSDK;
21
14
  /** Credit manager to open the account in. */
22
15
  creditManager: Address;
@@ -39,13 +32,6 @@ interface OpenStrategyFunded {
39
32
  * is what the `DEPOSIT` intent is for.
40
33
  **/
41
34
  creditAccount?: CreditAccountSlice;
42
- empty?: false;
43
- }
44
- /** Opening an account that holds nothing, for a position to land on later. */
45
- interface OpenStrategyEmpty {
46
- sdk: OnchainSDK;
47
- creditManager: Address;
48
- empty: true;
49
35
  }
50
36
  /**
51
37
  * Projected result of opening a brand-new leveraged position.
@@ -95,4 +81,4 @@ interface OpenStrategyState extends Omit<AccountProjection, "assets" | "quotas">
95
81
  */
96
82
  declare function buildOpenStrategyState(props: OpenStrategyProps): Promise<OpenStrategyState>;
97
83
  //#endregion
98
- export { OpenStrategyEmpty, OpenStrategyFunded, OpenStrategyProps, OpenStrategyState, buildOpenStrategyState };
84
+ export { OpenStrategyProps, OpenStrategyState, buildOpenStrategyState };
@@ -90,6 +90,8 @@ interface BuildMockSdkArgs {
90
90
  baseInterestRate?: bigint;
91
91
  /** Credit manager interest fee in Bps; feeds position metrics. */
92
92
  feeInterest?: number;
93
+ /** Quoted tokens the facade enables at once; feeds `checkQuotaCount`. */
94
+ maxEnabledTokens?: number;
93
95
  creditManager: Address;
94
96
  creditFacade: Address;
95
97
  /** Market underlying token (`market.pool.underlying`). */
@@ -1,6 +1,6 @@
1
1
  import { Asset } from "../../../base/types.js";
2
2
  import { OnchainSDK } from "../../../OnchainSDK.js";
3
- import { OpenStrategyFunded } from "../open-strategy.js";
3
+ import { OpenStrategyProps } from "../open-strategy.js";
4
4
  import "../../../index.js";
5
5
  import { MarketSdkExtras } from "../testing/market.js";
6
6
  import { Address } from "viem";
@@ -51,6 +51,6 @@ declare const case_underlying_1x: OpenStrategyCase;
51
51
  */
52
52
  declare const case_mixed_with_leftover: OpenStrategyCase;
53
53
  declare function buildOpenStrategySdk(extras?: MarketSdkExtras): OnchainSDK;
54
- declare function buildOpenStrategyProps(c: OpenStrategyCase, sdk: OnchainSDK): OpenStrategyFunded;
54
+ declare function buildOpenStrategyProps(c: OpenStrategyCase, sdk: OnchainSDK): OpenStrategyProps;
55
55
  //#endregion
56
56
  export { COLLATERAL_ANY, HALF_UND, KEEP_ANY, LEVERAGE_1X, LEVERAGE_2X, LEVERAGE_3X, LT, MARGIN_UND, OpenStrategyCase, buildOpenStrategyProps, buildOpenStrategySdk, case_mixed_with_leftover, case_underlying_1x, case_underlying_3x, quotaFor };
@@ -62,7 +62,21 @@ interface SimulationPrices {
62
62
  * {@link AccountProjection} vocabulary, plus the prices only a routed walk can
63
63
  * report.
64
64
  */
65
- interface OperationState extends AccountProjection, SimulationPrices {}
65
+ interface OperationState extends AccountProjection, SimulationPrices {
66
+ /**
67
+ * What the operation gives up, as `(out − in) / in`: the oracle value in the
68
+ * underlying of everything its routed legs and redemption request return,
69
+ * the expected claim included, against the value of what they spend.
70
+ * In `PERCENTAGE_FACTOR_1KK` (1_000_000 = 100%), negative for a loss.
71
+ *
72
+ * `undefined` where nothing was traded, where a leg cannot be priced, and on
73
+ * a {@link BorrowState}, which does not measure it: the rate compares an
74
+ * account against itself before and after, and a borrow's payout goes to the
75
+ * wallet rather than staying to be compared. What its route cost is on that
76
+ * state as `borrowed` against `totalDebt`.
77
+ */
78
+ executionCost: bigint | undefined;
79
+ }
66
80
  /**
67
81
  * What planning an intent yields: the operation chain, the state it projects,
68
82
  * and the calldata that realises it — or the error that stopped the plan.
@@ -429,12 +443,34 @@ interface WithdrawStrategyIntent {
429
443
  */
430
444
  interface WithdrawCeilings {
431
445
  /**
432
- * Largest partial withdrawal {@link WithdrawStrategyIntent} accepts: the one
433
- * whose proportional repayment leaves the debt at `minDebt`. `0n` when the
434
- * debt already sits below the floor, and always at least one unit under
435
- * `exit` — the last unit closes the account rather than shrinking it.
446
+ * Largest partial withdrawal the facade's `debtLimits` accept: the one whose
447
+ * proportional repayment leaves the debt at `minDebt`. `0n` when the debt
448
+ * already sits below the floor, and always at least one unit under `exit` —
449
+ * the last unit closes the account rather than shrinking it.
450
+ *
451
+ * `debtLimits` are not the only rule a withdrawal answers to, so this is a
452
+ * limit rather than the limit: {@link safePartial} is the one to offer.
436
453
  */
437
454
  partial: bigint;
455
+ /**
456
+ * Largest partial withdrawal {@link WithdrawStrategyIntent} actually accepts
457
+ * — {@link partial} once the safe-price collateral check has had its say,
458
+ * and never above it.
459
+ *
460
+ * A withdrawal hands funds over, and the facade weighs what it leaves behind
461
+ * at safe prices: `min` of a token's two feeds, or nothing at all where
462
+ * governance registered no reserve feed. Collateral the reserve feed marks
463
+ * down therefore backs less than a projection at main prices suggests, and
464
+ * the withdrawal stops earlier than `debtLimits` alone would say. This is
465
+ * the figure a slider and a Max button belong on.
466
+ *
467
+ * `0n` on an account already under the threshold at safe prices. That is not
468
+ * a rounding artefact and a smaller request does not help: a proportional
469
+ * withdrawal leaves the safe-price factor exactly where it found it, so no
470
+ * amount clears a threshold the account is already under. Such a position
471
+ * can still leave — see {@link exit}, which the check never refuses.
472
+ */
473
+ safePartial: bigint;
438
474
  /**
439
475
  * What leaving hands over: the account's net value, which is also the amount
440
476
  * at which a withdrawal turns into an exit. `0n` on an account whose debt
@@ -1,5 +1,7 @@
1
1
  import { Asset } from "../../../base/types.js";
2
2
  import { RouterCASlice } from "../../../router/types.js";
3
+ import { MarketSuite } from "../../../market/MarketSuite.js";
4
+ import { CreditSuite } from "../../../market/credit/CreditSuite.js";
3
5
  import { OnchainSDK } from "../../../OnchainSDK.js";
4
6
  import { CreditAccountSlice } from "../types.js";
5
7
  import "../../../index.js";
@@ -7,6 +9,18 @@ import { Address } from "viem";
7
9
  //#region src/onchain/accounts/intents/utils/common.d.ts
8
10
  /** Case-insensitive address equality. */
9
11
  declare const eq: (a: Address, b: Address) => boolean;
12
+ /**
13
+ * The suite and market behind a credit manager, or nothing where the register
14
+ * has no entry for it.
15
+ *
16
+ * For the reads a form calls on every keystroke, including before the SDK has
17
+ * finished attaching: a question the register cannot answer yet is not an
18
+ * error. Everything that prepares a transaction wants the throw instead.
19
+ */
20
+ declare function resolveCreditManager(sdk: OnchainSDK, creditManager: Address): {
21
+ suite: CreditSuite;
22
+ market: MarketSuite;
23
+ } | undefined;
10
24
  declare function toTargetDecimals(fromAmount: bigint, fromToken: Address, toToken: Address, sdk: OnchainSDK): bigint;
11
25
  /**
12
26
  * Router CA slice from the account slice. RouterV310 reads `ca.tokens` for
@@ -16,4 +30,4 @@ declare function toTargetDecimals(fromAmount: bigint, fromToken: Address, toToke
16
30
  */
17
31
  declare function toRouterCaSlice(creditAccount: CreditAccountSlice, expectedBalances?: Asset[]): RouterCASlice;
18
32
  //#endregion
19
- export { eq, toRouterCaSlice, toTargetDecimals };
33
+ export { eq, resolveCreditManager, toRouterCaSlice, toTargetDecimals };
@@ -15,6 +15,19 @@ import { Address } from "viem";
15
15
  * behave consistently everywhere downstream.
16
16
  */
17
17
  declare function toCreditAccountSlice(ca: CreditAccountDataPayload): CreditAccountSlice;
18
+ /**
19
+ * The slice a flow that has no account yet quotes against.
20
+ *
21
+ * Nothing of it exists on chain until the transaction lands, and nothing has
22
+ * to: the pathfinder is asked about the credit manager, and every balance the
23
+ * flow reasons about is one the transaction itself puts there. The zero
24
+ * address stands in for the account so the shape is complete.
25
+ */
26
+ declare function unopenedAccountSlice(args: {
27
+ creditManager: Address;
28
+ creditFacade: Address;
29
+ underlying: Address;
30
+ }): CreditAccountSlice;
18
31
  /**
19
32
  * Reads an account by address and narrows it to {@link CreditAccountSlice}.
20
33
  *
@@ -26,4 +39,4 @@ declare function toCreditAccountSlice(ca: CreditAccountDataPayload): CreditAccou
26
39
  */
27
40
  declare function fetchCreditAccountSlice(sdk: OnchainSDK, creditAccount: Address): Promise<CreditAccountSlice>;
28
41
  //#endregion
29
- export { fetchCreditAccountSlice, toCreditAccountSlice };
42
+ export { fetchCreditAccountSlice, toCreditAccountSlice, unopenedAccountSlice };
@@ -1,11 +1,11 @@
1
- import { fetchCreditAccountSlice, toCreditAccountSlice } from "./credit-account-slice.js";
1
+ import { fetchCreditAccountSlice, toCreditAccountSlice, unopenedAccountSlice } from "./credit-account-slice.js";
2
2
  import { CandidateToken, isPhantomToken, isRedemptionPhantomToken, pickFattestNonPhantomToken, rankAccountTokens } from "./pick-token.js";
3
3
  import { LegProbe, collectPriceImpact, lossRate, startProbe } from "./price-impact.js";
4
4
  import { OpenStrategyLeg, RouterPaths, SwapLeg, createOraclePaths, createRouterPaths } from "./router-path.js";
5
5
  import { adjustStateToSnapshot } from "./adjust-state-to-snapshot.js";
6
6
  import { assembleOperationCalls } from "./assemble-operation-calls.js";
7
7
  import { calcBorrowedAmountPlusInterestAndFees } from "./borrowed-amount-plus-interest-and-fees.js";
8
- import { eq, toRouterCaSlice, toTargetDecimals } from "./common.js";
8
+ import { eq, resolveCreditManager, toRouterCaSlice, toTargetDecimals } from "./common.js";
9
9
  import { LedgerSnapshot, OperationLedger } from "./ledger.js";
10
10
  import { clearedQuotas, getQuotasForUpdate, quotasAfterUpdate } from "./quotas-for-update.js";
11
- export { CandidateToken, LedgerSnapshot, LegProbe, OpenStrategyLeg, OperationLedger, RouterPaths, SwapLeg, adjustStateToSnapshot, assembleOperationCalls, calcBorrowedAmountPlusInterestAndFees, clearedQuotas, collectPriceImpact, createOraclePaths, createRouterPaths, eq, fetchCreditAccountSlice, getQuotasForUpdate, isPhantomToken, isRedemptionPhantomToken, lossRate, pickFattestNonPhantomToken, quotasAfterUpdate, rankAccountTokens, startProbe, toCreditAccountSlice, toRouterCaSlice, toTargetDecimals };
11
+ export { CandidateToken, LedgerSnapshot, LegProbe, OpenStrategyLeg, OperationLedger, RouterPaths, SwapLeg, adjustStateToSnapshot, assembleOperationCalls, calcBorrowedAmountPlusInterestAndFees, clearedQuotas, collectPriceImpact, createOraclePaths, createRouterPaths, eq, fetchCreditAccountSlice, getQuotasForUpdate, isPhantomToken, isRedemptionPhantomToken, lossRate, pickFattestNonPhantomToken, quotasAfterUpdate, rankAccountTokens, resolveCreditManager, startProbe, toCreditAccountSlice, toRouterCaSlice, toTargetDecimals, unopenedAccountSlice };
@@ -0,0 +1,80 @@
1
+ import { OnchainSDK } from "../../OnchainSDK.js";
2
+ import { CreditAccountSlice, WithdrawCeilings } from "./types.js";
3
+ import "../../index.js";
4
+ import { Address } from "viem";
5
+ //#region src/onchain/accounts/intents/withdraw-limits.d.ts
6
+ interface WithdrawLimitsProps {
7
+ creditAccount: CreditAccountSlice;
8
+ sdk: OnchainSDK;
9
+ /**
10
+ * Token the withdrawal liquidates. Defaults to the account's largest
11
+ * non-phantom balance, which is what the planner reaches for when the intent
12
+ * names none.
13
+ */
14
+ sourceToken?: Address;
15
+ }
16
+ /**
17
+ * Every limit a `WITHDRAW` answers to, in underlying units.
18
+ *
19
+ * The one place they are assembled, so the figure a form is offered and the
20
+ * figure the collateral guard names when it turns a withdrawal down cannot
21
+ * drift apart: `CreditAccountOperationsService` reports this, and the guard
22
+ * quotes it back.
23
+ *
24
+ * @param props - Account slice, the SDK holding its market, and optionally the
25
+ * collateral the withdrawal would be funded from
26
+ * @returns The three limits, see {@link WithdrawCeilings}
27
+ **/
28
+ declare function withdrawLimits(props: WithdrawLimitsProps): WithdrawCeilings;
29
+ interface MaxSafeWithdrawalProps {
30
+ creditAccount: CreditAccountSlice;
31
+ sdk: OnchainSDK;
32
+ /**
33
+ * Token the withdrawal liquidates. Defaults to the account's largest
34
+ * non-phantom balance, which is what the planner reaches for when the intent
35
+ * names none.
36
+ */
37
+ sourceToken?: Address;
38
+ /**
39
+ * Health factor the withdrawal has to leave behind, in basis points. The
40
+ * facade's own threshold answers "would this land"; a form holding the
41
+ * account to something stricter passes its own.
42
+ */
43
+ targetHF: bigint;
44
+ }
45
+ /**
46
+ * Largest proportional withdrawal the safe-price collateral check still clears,
47
+ * in underlying units.
48
+ *
49
+ * A withdrawal hands funds over, so the facade weighs the account it leaves
50
+ * behind at safe prices rather than main ones — see {@link collateralValuation}.
51
+ * That is a second limit on top of the facade's `debtLimits`, and the two are
52
+ * independent: a caller wanting the amount a form may actually offer takes the
53
+ * lesser of this and `maxProportionalWithdrawal`.
54
+ *
55
+ * The arithmetic is the check solved for the amount. Taking `W` out at fixed
56
+ * leverage repays `dD = D·W/C`, so `W·TVL/C` of value is sold out of the source
57
+ * token; each dollar of that sale costs the check the source's threshold times
58
+ * its safe-to-main price ratio, while the repayment relieves `targetHF` per
59
+ * dollar of debt. Both terms are linear in `W`, which is why one division
60
+ * answers instead of a search — and why the answer is exact rather than a
61
+ * bound, as long as the plan really does fund itself from `sourceToken`.
62
+ *
63
+ * Two consequences worth stating, because they surprise:
64
+ *
65
+ * - An account whose collateral is entirely a token the reserve feed marks
66
+ * down cannot withdraw at all once it is under the threshold. A proportional
67
+ * withdrawal scales collateral and debt together, so it leaves the safe-price
68
+ * factor exactly where it found it — no amount climbs back over.
69
+ * - Leaving entirely is never refused for this reason: the exit settles the
70
+ * debt instead of shrinking it, and a check with no debt to divide by has
71
+ * nothing to refuse.
72
+ *
73
+ * @returns Amount in underlying units. The account's net value when safe prices
74
+ * do not limit the withdrawal at all, so the caller's `min` is a no-op; `0n`
75
+ * when the account already sits below `targetHF` at safe prices, and only the
76
+ * exit is left
77
+ **/
78
+ declare function maxSafeWithdrawal(props: MaxSafeWithdrawalProps): bigint;
79
+ //#endregion
80
+ export { MaxSafeWithdrawalProps, WithdrawLimitsProps, maxSafeWithdrawal, withdrawLimits };