import { Bps, Timestamp, TokenAmount } from "../../model/primitives.js"; import { Curator } from "../../model/curators.js"; import { CreditManagerPausedError, DebtOutOfRangeError, ForbiddenTokenError, InsufficientBalanceError, InsufficientCollateralError, InsufficientPoolLiquidityError, LeverageOutOfRangeError, MarketExpiredError, QuotaAboveMaxError, QuotaInactiveError, QuotaLimitReachedError, QuotaUnchangedError, ReservePriceLimitedError } from "../../model/errors/operation-errors.js"; import { CreditAccountNotEmptyError, CreditAccountNotFoundError, MultipleDelayedWithdrawalsError, NoDelayedRouteError, NoRecordedIntentError, NoStrategyTargetCollateralError, UnexpectedFailureError, UnsupportedCollateralTokenError, UnsupportedTokenPairError, WithdrawalInProgressError } from "../../model/errors/prepare-errors.js"; import { PoolOpportunityKey, StrategyOpportunityKey } from "../../model/opportunities.js"; import { Position, PositionCollateral, StrategyPosition, StrategyPositionKey } from "../../model/positions.js"; import { SDKReturn } from "../../model/result.js"; import { PositionClaimableWithdrawal } from "../../model/withdrawals.js"; import "../../model/index.js"; import { Asset } from "../../onchain/base/types.js"; import { MultiCall } from "../../onchain/types/transactions.js"; import { PoolSimulation } from "../../onchain/pools/types.js"; import { AccountCalculatorOperation } from "../../onchain/accounts/intents/operations.js"; import { ClaimRemainder, DelayedStart, ExecutionCost, OperationState, PathLossRate, ResumableIntent, RouteErrors, WithPartialState, WithdrawCeilings } from "../../onchain/accounts/intents/types.js"; import { BorrowState } from "../../onchain/accounts/intents/borrow.js"; import { LeverageBand } from "../../onchain/accounts/intents/leverage-band.js"; import { OpenStrategyState } from "../../onchain/accounts/intents/open-strategy.js"; import { PoolOperationError } from "../../onchain/validation/bundles/checkPoolOperation.js"; import "../../onchain/index.js"; import { Address } from "viem"; //#region src/sdk/prepare/types.d.ts /** Recoverable target-token quota, computed from loaded market state. */ export interface QuotaBufferState { /** Validated strategy context, with a known target collateral. */ position: StrategyPosition & { targetCollateral: NonNullable; }; /** Target value times LT, before reserve and protocol-step rounding. */ baseQuota: bigint; currentQuota: bigint; /** Positive increase available under the pool and account limits. */ quotaIncrease: bigint; } export interface MaxBorrowAndWithdrawOptions { /** Main-price HF threshold, in basis points; defaults to 10101. */ targetHF?: bigint; /** Safe-price HF threshold, in basis points; defaults to 10001. */ targetSafeHF?: bigint; } export interface MaxWithdrawCollateralOptions { /** Main-price HF threshold, in basis points; defaults to 10101. */ targetHF?: bigint; /** Safe-price HF threshold, in basis points; defaults to 10001. */ targetSafeHF?: bigint; } /** * What any operation on an existing account can answer with: the engine's * shared guards, the missing account, and a wrapped crash. **/ export type AccountFlowError = CreditManagerPausedError | MarketExpiredError | ForbiddenTokenError | QuotaLimitReachedError | InsufficientCollateralError | ReservePriceLimitedError | InsufficientBalanceError | CreditAccountNotFoundError | UnexpectedFailureError; /** Same guards for the account-less open flow. */ export type OpenFlowError = CreditManagerPausedError | MarketExpiredError | ForbiddenTokenError | QuotaLimitReachedError | InsufficientCollateralError | InsufficientBalanceError | UnexpectedFailureError; /** * What every error of a two-route request carries on top of its own code, * see {@link StrategyRoutesResult}. * * `errors` says why each route is missing, which is the answer a form needs * even when neither exists: the error itself is the instant route's — the one * a caller can usually act on — or the delayed route's when the instant one * did not get far enough to have a reason of its own. **/ export interface WithRouteErrors { errors: RouteErrors; } /** * Where a pool operation leaves the wallet: the two sides of the trade as * `sdk.pools` prices them, plus what a screen needs beside them and the raw * simulation cannot know — whose market this is, and how large the position * ends up. **/ export interface LpState extends PoolSimulation { /** * Curator of the market the pool belongs to, in the same shape * {@link PoolOpportunity} and {@link CreditOperationMarket} report it. **/ curator: Curator; /** * The wallet's position in this pool once the operation has run, in the * market's underlying. * * Denominated like {@link PoolPosition.netValue}, so a screen showing both * reads one token: on an RWA market that is the unwrapped asset — USDC * rather than the dcUSDC the pool actually holds. * * Does not account for withdrawal fee: this is what the remaining shares * are worth, not what leaving with them would pay. **/ netValue: TokenAmount; } /** * What a pool deposit or withdrawal comes to. * * Shaped like {@link StrategyResult} so both kinds of result are consumed the * same way, with the pool's own numbers as the state: the ERC-4626 * conversion applied to the amount, at the rate of the block the market was * loaded at. **/ export interface LpResult { /** * Always empty: a pool operation is a single transaction, so there is no * chain of steps to show. Present so callers can treat both kinds of * result alike. **/ operations: []; /** * What the wallet parts with and what it receives, the zapper the * transaction goes through when one is involved, and where the position ends * up, see {@link LpState}. **/ state: LpState; /** * The transaction implementing the operation: exactly one, since a pool * operation is a single call on the pool or on its zapper. **/ calls: MultiCall[]; /** Block of the chain state this result was computed from. */ blockNumber: number; /** Unix seconds of {@link blockNumber}. */ timestamp: Timestamp; } /** * What an operation on an existing credit account comes to. **/ export interface StrategyResult { /** * The logical steps, each carrying the amounts it was computed from. * Useful for showing the user what will happen, and for pinning behaviour * in tests. **/ operations: AccountCalculatorOperation[]; /** * Projected account state once the operations execute: TVL, debt, * balances and quotas. **/ state: OperationState; /** * Credit-facade multicall implementing the operations, ready to be sent * through `sdk.accounts`. **/ calls: MultiCall[]; /** Block of the chain state this result was computed from. */ blockNumber: number; /** Unix seconds of {@link blockNumber}. */ timestamp: Timestamp; } /** * What the tail of a delayed operation comes to: {@link StrategyResult}, plus * whether the claim it was built on settled the withdrawal whole. **/ export interface FinalizeResult extends StrategyResult { /** * What the claim did not bring, when the venue settled part of the matured * withdrawal and left the rest of it queued — only a legacy Mellow multivault * does. `undefined` everywhere else, which is the normal case: one request, * one claim, one tail. * * When it is set, the result beside it serves only the share that arrived, * and the operation is not over: pass `remainder.intent` back to * {@link IOpportunitiesPrepare.finalize} with the next claim, see * {@link ClaimRemainder}. **/ remainder: ClaimRemainder | undefined; } /** * What the leading half of a delayed operation comes to: the request * transaction, plus what it recorded for the tail and where that tail leads. * * Shaped like {@link StrategyResult} with one field more, so the instant and * the delayed route of the same request are compared side by side — and they * are meant to be compared on the same footing, so `state` is the end of the * operation in both, not the end of the transaction. **/ export interface DelayedStrategyResult { /** * {@inheritDoc StrategyResult.operations} **/ operations: AccountCalculatorOperation[]; /** * Where the operation ends: the account once the redemption has matured, * been claimed and the tail has run — the same place the instant route * reaches in one transaction, which is what makes the two comparable. * * The tail's half of it is an estimate priced by the oracle: the funds it * trades do not exist yet, so no route can be quoted for them. The state * the request alone lands in — source spent, withdrawal position in its * place, debt untouched — is `delayed.afterRequest`. **/ state: OperationState; /** * {@inheritDoc StrategyResult.calls} **/ calls: MultiCall[]; /** * When the tail can be run, and what the request recorded for it, see * {@link DelayedStart}. **/ delayed: DelayedStart; /** Block of the chain state this result was computed from. */ blockNumber: number; /** Unix seconds of {@link blockNumber}. */ timestamp: Timestamp; } /** * What one of the two flows that sell a position asset — * {@link IOpportunitiesPrepare.withdrawStrategy} and * {@link IOpportunitiesPrepare.adjustLeverage} — would yield each way it can be * served. * * Whether the account can sell that asset on the router, redeem it through its * issuer, or both, is not something the caller can know up front, so both routes * are quoted from one request. A route the account cannot take is `undefined` * with its error in `errors`, which is what lets a form offer exactly the * routes that exist; a failure means neither does, and the error still carries * `errors`, see {@link WithRouteErrors}. **/ export interface StrategyRoutesResult { /** * The router route: one transaction, settled on the spot. `undefined` * when the asset cannot be sold, see `errors.instant`. **/ instant: StrategyResult | undefined; /** * The request half of the redemption route, which * {@link IOpportunitiesPrepare.finalize} completes once it matures. * `undefined` when the route does not exist — no redemption venue for the * asset, or a request that settles at once anyway — see `errors.delayed`. **/ delayed: DelayedStrategyResult | undefined; /** * Why a missing route is missing, see {@link RouteErrors}. **/ errors: RouteErrors; /** Block of the chain state this result was computed from. */ blockNumber: number; /** Unix seconds of {@link blockNumber}. */ timestamp: Timestamp; } /** * What opening a new leveraged position comes to. * * The only result that reports both an expected and a floor branch: opening * takes both from a single pathfinder call, and `openCA` consumes both. **/ export interface OpenStrategyResult { /** * Everything the opening arrives at: the projection, both branches of the * post-open balances and quotas, and the router path `openCA` is handed. **/ state: OpenStrategyState; /** Block of the chain state this result was computed from. */ blockNumber: number; /** Unix seconds of {@link blockNumber}. */ timestamp: Timestamp; } /** * What taking a loan against collateral comes to. * * Shaped like {@link OpenStrategyResult} — a borrow opens its account too, so * there is no chain of steps to report — with the whole projection on the * state rather than two branches of balances, see {@link BorrowState}. **/ export interface BorrowResult { /** * Everything the loan arrives at: the collateral and the debt it backs, the * payout expected and its floor, the position metrics a screen shows beside * them, and the router path `openCA` is handed. **/ state: BorrowState; /** Block of the chain state this result was computed from. */ blockNumber: number; /** Unix seconds of {@link blockNumber}. */ timestamp: Timestamp; } /** * What opening an account that holds nothing comes to: the block it was * cleared at, and nothing else. * * The one prepared operation with no state to report. Every other result * describes where the account lands, but this one lands it holding nothing and * owing nothing — there is no collateral to value, no debt to weigh and no * health factor to read. What the preparation is for is the refusal it can * answer with instead: a market that takes no multicall. **/ export interface EmptyCreditAccountResult { /** Block of the chain state this result was computed from. */ blockNumber: number; /** Unix seconds of {@link blockNumber}. */ timestamp: Timestamp; } /** * Shared knobs. Both default to the SDK's own defaults when omitted. **/ export interface PrepareOptions { /** Router slippage in PERCENTAGE_FORMAT (100% = 10_000). */ slippage?: number; /** * Extra quota headroom in PERCENTAGE_FORMAT, to survive price drift between * the preparation and execution. **/ quotaReserve?: number; } /** * Position to prepare against. A `StrategyPosition` from * `sdk.positions.list()` satisfies this, as does a bare key. **/ export type PositionInput = StrategyPositionKey; /** * Pool to prepare against. A `PoolOpportunity` from * `sdk.opportunities.list()` satisfies this, as does a bare key. **/ export type PoolInput = PoolOpportunityKey; /** * Market to open a new position in. A `StrategyOpportunity` from * `sdk.opportunities.list()` satisfies this, as does a bare key. **/ export type StrategyInput = StrategyOpportunityKey; export interface DepositStrategyParams extends PrepareOptions { /** * Collateral to add: the market underlying, or its unwrapped asset on an RWA * market (USDC rather than dcUSDC). **/ token: Address; amount: bigint; /** Native value to attach when paying a wrapped-native market in the coin. */ value?: bigint; /** * Token the position ends up in. Defaults to the account's most valuable * non-phantom, non-underlying balance. **/ positionToken?: Address; /** * Target total leverage scaled by `LEVERAGE_DECIMALS` (300n = 3x). Omit to * keep the account's current leverage. **/ targetLeverage?: bigint; } export interface WithdrawStrategyParams extends PrepareOptions { /** * Amount the wallet receives, denominated in `tokenOut`. `MAX_UINT256`, or * anything at or above the account's net value, turns the flow into an exit, * see {@link IOpportunitiesPrepare.withdrawStrategy}. **/ amount: bigint; /** Token recipient. */ to: Address; /** * Token the wallet receives. Defaults to the market underlying, force-unwrapped * to the RWA asset on an RWA market. **/ tokenOut?: Address; /** * Token liquidated to fund the withdrawal. Defaults to the account's most * valuable non-phantom balance. **/ sourceToken?: Address; } export interface RepayStrategyParams extends PrepareOptions { /** * Funding token: the market underlying, which needs no conversion and is * repaid where it lands, or — on an RWA market — the unwrapped asset behind * it (USDC rather than dcUSDC), which this flow wraps on the way in. **/ token: Address; /** * Amount taken from the wallet. Anything above the outstanding debt settles * it in full and stays on the account as collateral, so a caller clearing the * account can add a buffer for the interest that accrues before the * transaction lands, see {@link IOpportunitiesPrepare.maxRepay}. * `MAX_UINT256` settles the debt and sizes that buffer itself. **/ amount: bigint; /** Native value to attach when paying a wrapped-native market in the coin. */ value?: bigint; } export interface AdjustLeverageParams extends PrepareOptions { /** * Target total leverage scaled by `LEVERAGE_DECIMALS` (300n = 3x); 100n means * no debt. **/ targetLeverage: bigint; /** * Position token to buy into or sell out of. Defaults to the account's most * valuable non-phantom, non-underlying balance. **/ token?: Address; } export interface AddCollateralParams extends PrepareOptions { /** Position token to deposit; nothing else is accepted. */ token: Address; amount: bigint; /** Native value to attach when paying a wrapped-native market in the coin. */ value?: bigint; } export interface BorrowAndWithdrawParams { /** Wallet receiving the tokens. */ to: Address; /** Exact payout in the underlying, or the asset behind an RWA wrapper. */ amount: bigint; } export interface WithdrawCollateralParams extends PrepareOptions { /** Token to move out; must already sit on the account. */ token: Address; amount: bigint; /** Wallet receiving the tokens. */ to: Address; } export interface UpdateQuotaParams extends PrepareOptions { /** Collateral token on the account, other than the underlying. */ token: Address; /** * Target quota in underlying units; 0 disables it. Omit to size it to the * balance: its value in underlying × LT, raised by `quotaReserve`. **/ quota?: bigint; } export interface OpenStrategyParams extends PrepareOptions { /** Collateral coming from the wallet, in their own tokens. */ collateral: Asset[]; /** * Target total leverage scaled by `LEVERAGE_DECIMALS` (300n = 3x). **/ leverage: bigint; /** * Token the position ends up in. Defaults to the opportunity's target * collateral. **/ targetToken?: Address; /** Collateral to leave unswapped; everything else is routed into the target. */ leftoverBalances?: Asset[]; /** * Existing credit account to open the position on, instead of creating one. * * Any account of `strategy.creditManager` that carries no debt and no * quotas qualifies. The projection is identical either way; only the * transaction differs, and `execute.buildTx` reads which one to build off * the result's own `state.creditAccount`. **/ creditAccount?: Address; } export interface BorrowParams extends PrepareOptions { /** * Token the wallet puts up as collateral. Must be a collateral token of the * market, and cannot be {@link borrowToken} — the payout is swept off the * account, and a sweep takes the whole balance of the token it names. **/ collateralToken: Address; /** Amount of {@link collateralToken} that leaves the wallet. */ collateralAmount: bigint; /** * Token the wallet is paid the loan in. The market underlying is handed over * as it is borrowed; anything else the router has a path to is bought with * the borrowed underlying first, and then {@link BorrowResult} reports both * what that trade is expected to return and its floor. * * An RWA market is paid in the asset its underlying wraps — `USDC`, not the * `dcUSDC` the pool lends — because the wrapper cannot leave the account. * The two convert one for one through the market's vault, so that payout is * exact like the underlying's. Naming the wrapper is refused with * `unsupportedCollateralToken`. **/ borrowToken: Address; /** * Amount of {@link borrowToken} the wallet asks for. It is the debt exactly * when `borrowToken` is the market underlying, and the same amount in the * underlying's own decimals when it is the asset an RWA market unwraps into; * otherwise the debt is what the oracle prices that much of it at, and what * actually arrives is the router's answer. **/ borrowAmount: bigint; /** * Existing credit account to draw the loan on, instead of opening one. * * Any account of `strategy.creditManager` that carries no debt and no * quotas qualifies. Only the transaction differs; `execute.buildTx` reads * which one to build off the result's own `state.creditAccount`. * * Balances already sitting on it are left where they are and are **not** * counted towards the health factor, so the loan this allows is the one the * named collateral alone carries. The exception is a balance in * {@link borrowToken}: the payout sweep takes the whole balance of the token * it names, so that one leaves with the loan. **/ creditAccount?: Address; } /** * What a borrow form knows before it knows the amount: everything * {@link BorrowParams} carries except the loan itself, which is the answer. **/ export interface MaxBorrowParams { /** Token the wallet would put up, as in {@link BorrowParams}. */ collateralToken: Address; /** Amount of {@link collateralToken} that would leave the wallet. */ collateralAmount: bigint; /** Token the loan would be paid in; the ceiling comes back in its units. */ borrowToken: Address; /** * Health factor the loan should leave the account at, in basis points. * Omitted, the SDK holds it to the threshold a form would. **/ targetHF?: bigint; /** * Extra quota headroom in PERCENTAGE_FORMAT. Pass what the borrow itself * will pass: a quota short of the collateral's weighted value is what caps * the loan, so a different reserve here answers about a different loan. **/ quotaReserve?: number; } export interface LpParams { /** * On deposit: amount of `tokenIn`. On withdraw: amount of `tokenOut`, which * the pool's `withdraw` takes as is and prices in shares itself. **/ amount: bigint; /** * Wallet funding the deposit or receiving the withdrawal. Required because it * is baked into the calldata. **/ wallet: Address; /** * Token the user parts with. Defaults to the pool underlying on deposit and to * the pool shares on withdrawal. **/ tokenIn?: Address; /** * Token the user receives. Defaults to the only route available for `tokenIn`; * required when the pool offers several, otherwise the preparation answers * with `unsupportedTokenPair`. **/ tokenOut?: Address; } /** * Same shape as {@link LpParams}, but {@link IOpportunitiesPrepare.redeem} * treats `amount` as the pool shares to burn rather than the underlying to * receive. **/ export interface LpRedeemParams { /** * Amount of `tokenIn` — pool shares, or the zapper token that wraps them — * to redeem. **/ amount: bigint; wallet: Address; tokenIn?: Address; tokenOut?: Address; } export interface FinalizeParams extends PrepareOptions { /** * The matured withdrawal to claim, from * `sdk.positions.getCurrentWithdrawals()`. **/ claimable: PositionClaimableWithdrawal; /** * The operation to resume. Defaults to the one the request recorded in the * withdrawal's `extraData`, which is what * {@link PositionClaimableWithdrawal.intent} decodes; pass it explicitly * when the compressor is too old to report it — as a Mellow one is, since a * Mellow request cannot carry an intent at all — or when a previous claim * served only part of the operation and left one in * {@link FinalizeResult.remainder}. **/ intent?: ResumableIntent; } /** * Everything a wallet can do to a pool or a credit account, prepared. * * On-chain only: every method reads live state and, for strategies, asks the * pathfinder for real swap paths. Nothing is executed and nothing is signed — * the result is the numbers plus the calldata that would produce them. * * Not to be confused with `src/onchain/preview`, which goes the other way: it takes * calldata that already exists and reports what it would do. * * Every refusable method answers `SDKReturn` and names, in its own signature, * exactly the errors its flow can answer with — the union is the list of * everything a caller has to handle, checked by the compiler. None of them * throws: a chain that cannot be reached or a crash on the way arrives as * `unexpectedFailure` with the cause attached. * * Every method that reports a state reports one when it refuses too: the error * carries `state`, the same shape the answer beside it would have had, with * the fields the request never got far enough to say left out — see * {@link WithPartialState}. A form that asked "what would this do to my * position" is told as much of it as there was, and can explain the no in * numbers rather than in a code alone. * * The bare readers stay outside the envelope. The ones that read an account * answer their number and throw on an account or chain the SDK does not hold; * the synchronous ones ({@link leverageBand}, {@link withdrawableCollaterals}, * {@link maxBorrow}) weigh state already loaded and say "nothing available" * with `undefined`, an empty list or `0n`. **/ export interface IOpportunitiesPrepare { /** Synchronous quota-buffer state from loaded chain data. No freshness refresh * or account RPC read. Ineligible positions return undefined; unexpected * failures are thrown. extraQuotas includes reservations absent from the position. */ getQuotaBufferState(position: Position, extraQuotas?: readonly (Pick & { quota: bigint; })[]): QuotaBufferState | undefined; /** * Depositing into a pool: underlying in, shares out. * * The trade itself is the pool's share rate applied to the amount, which is * loaded already; the wait is for the one thing that is not, the shares the * wallet holds, without which {@link LpState.netValue} cannot be said. **/ deposit(pool: PoolInput, params: LpParams): Promise>>; /** * Taking underlying out of a pool: `amount` is the `tokenOut` the wallet * wants back, and the pool burns whatever shares that costs. * * The LP counterpart of {@link withdrawStrategy} / {@link withdrawCollateral}, * which act on credit accounts. **/ withdraw(pool: PoolInput, params: LpParams): Promise>>; /** * Redeeming pool shares: `amount` is the `tokenIn` the wallet parts with, * and the reported state is the underlying it converts to. **/ redeem(pool: PoolInput, params: LpRedeemParams): Promise>>; /** * Opening a leveraged position from wallet collateral. * * There is no account to walk yet, so the result carries no operation list — * it feeds `sdk.accounts.openCA` instead. * * `creditAccount` puts the position on an account the wallet already holds * rather than creating one. **/ openNewStrategy(strategy: StrategyInput, params: OpenStrategyParams): Promise>>; /** * Handing a wallet an account that holds nothing: no collateral, no debt, no * quotas and no route quoted. It exists so a wallet can hold an account * ahead of having a use for one, and so the two flows that put something on * an account have one to name as their `creditAccount`. * * The market is the whole request, and the only thing that can refuse it is * the market itself: a facade that is paused or past its expiration takes no * multicall, so an account cannot be opened there either. **/ openEmptyCreditAccount(strategy: StrategyInput): Promise>; /** * Borrowing against collateral: one transaction opens an account, puts the * collateral on it, draws the loan and pays it out to the wallet. * * The account is left holding the collateral and owing the debt, and nothing * else — which is what tells this apart from {@link openNewStrategy}, where * the borrowed funds stay on the account as part of the position. There is * no leverage to name for the same reason: the loan is the amount asked for. * * The payout leaves the account, so the market weighs what is left at safe * prices, and a loan the remaining collateral cannot carry there comes back * as `insufficientCollateral` rather than reverting on arrival. * * `creditAccount` draws the loan on an account the wallet already holds * instead of opening another, as {@link openNewStrategy} does. **/ borrow(strategy: StrategyInput, params: BorrowParams): Promise>>; /** * Growing a position: collateral in, debt drawn on top, both converted into * the position token. * * Leverage stays put unless `targetLeverage` asks for more. **/ depositStrategy(position: PositionInput, params: DepositStrategyParams): Promise>>; /** * Shrinking a position: part of its net value goes to the wallet and debt is * repaid in the same proportion, so leverage is unchanged. * * Answers with both routes the withdrawal can take — sold through the router * now, or redeemed through the source's issuer and finished days later — since * the source token decides which of them exist, see * {@link StrategyRoutesResult}. * * `MAX_UINT256` — or any amount at or above the account's net value — is an * exit instead: the quotas are dropped, the position is sold whole in one * many-to-one route, the debt is settled in full and every balance left goes * to `to`. `tokenOut` is ignored, since the proceeds are already the * underlying (unwrapped on an RWA market). The account stays open with * nothing on it. * * An exit has both routes as well, which is what lets an account whose * position only redeems through its issuer leave at all: the delayed route * redeems `sourceToken` whole and records the exit, and {@link finalize} * rebuilds it against the account the claim finds — the debt as it stands by * then, whatever else is on the account, everything sold in one route. * * @see withdrawCollateral to move an asset out without touching debt, which * raises leverage instead. **/ withdrawStrategy(position: PositionInput, params: WithdrawStrategyParams): Promise>>; /** * How much {@link withdrawStrategy} can take out, every end of it, in * underlying units: `safePartial` is the largest partial withdrawal the flow * accepts, `partial` the same figure before the safe-price collateral check * has had its say, and `exit` the net value leaving entirely hands over. * * More than one number because the range has a hole in it: between the * largest partial and `exit` the flow refuses with `debtOutOfRange`, since * the leftover loan would sit below the floor. A form driving a slider off * `safePartial` and a Max button off `exit` describes what the account can * actually do; a form using either alone will misstate one of them — see * {@link WithdrawCeilings}, which spells out how far apart they can be and * why the two partial figures differ. * * `sourceToken` is the collateral the withdrawal would be funded from, the * same argument {@link withdrawStrategy} takes. It matters because selling * one collateral and selling another cost the safe-price check different * amounts; omitted, both this and the flow itself reach for the account's * largest non-phantom balance. * * `targetHF` is the health factor `safePartial` has to leave behind, in * basis points. The default is the facade's own threshold; a form holding * the account to something stricter passes its own, so the ceiling it * offers clears its own bar rather than landing a basis point under it. * * Taking everything out needs none of the figures: send `MAX_UINT256` to * {@link withdrawStrategy} and the exit is what runs, named rather than * priced. * * A bare read: it answers its numbers, and throws on an account or a chain * the SDK does not hold. **/ maxWithdraw(position: PositionInput, sourceToken?: Address, targetHF?: bigint): Promise; /** * Paying debt down with funds from the wallet: collateral stays where it is, * so net value grows by what was repaid, leverage falls and the health factor * rises. The flow to reach for when a position is close to liquidation. * * A partial repayment is two calls and nothing else: the funding lands and * the debt shrinks, quotas untouched — they still back a loan. * * A repayment that covers the whole debt clears the account's quotas with it, * which the facade requires of a loan going to zero, and asks for the full * outstanding amount, so nothing is left owing because interest moved between * this preparation and the transaction. `MAX_UINT256` is how to ask for that * settlement without naming a figure: the wallet is charged the debt plus a * 10bps margin for the interest still to come, and whatever the facade does * not take stays on the account. **/ repayStrategy(position: PositionInput, params: RepayStrategyParams): Promise>>; /** * Debt {@link repayStrategy} would have to cover to clear the account, in * underlying units: principal, interest and fees as of this read. Interest * keeps accruing, so a wallet meaning to settle sends this with a buffer. * * A bare read: it answers its number, and throws on an account or a chain * the SDK does not hold. **/ maxRepay(position: PositionInput): Promise; /** * Retargeting leverage at fixed collateral: debt moves, own funds do not. * * Answers with both routes, like {@link withdrawStrategy}, since deleveraging * sells the position token and may only be able to redeem it. Raising leverage * buys instead, so there the delayed route is always absent with * `errors.delayed` set to `noDelayedRoute`. **/ adjustLeverage(position: PositionInput, params: AdjustLeverageParams): Promise>>; /** * Putting the position token onto the account at fixed debt, which lowers * leverage and raises the health factor. **/ addCollateral(position: PositionInput, params: AddCollateralParams): Promise>>; /** Maximum additional loan paid out without changing existing balances or quotas. * Returns payout token units; zero when no amount can be borrowed. */ maxBorrowAndWithdraw(position: PositionInput, options?: MaxBorrowAndWithdrawOptions): Promise; /** Increase existing debt and pay the exact amount to the supplied recipient. * Ordinary markets pay underlying; RWA markets unwrap into its asset. */ borrowAndWithdraw(position: PositionInput, params: BorrowAndWithdrawParams): Promise>>; /** * Moving one asset that already sits on the account out to the wallet, at * fixed debt — so TVL falls and leverage rises. * * @see withdrawStrategy for the deleveraging withdrawal, which repays debt in * proportion and leaves leverage unchanged. **/ withdrawCollateral(position: PositionInput, params: WithdrawCollateralParams): Promise>>; /** * Changing the quota of one token the account already holds, at fixed debt * and balances: how much of it counts as collateral, and the quota fee paid * for it. * * A target is sent strictly, so the transaction reverts rather than end * below it. An omitted target is sized to the balance and capped at the * pool's available quota; the call then accepts a partial fill that keeps the * token enabled. **/ updateQuota(position: PositionInput, params: UpdateQuotaParams): Promise>>; /** * The leverages a deposit of a given size can reach in this market: the * range a leverage slider should mark as available. * * `maxLeverage` on the opportunity is the ceiling the liquidation threshold * allows, and it is the same number whatever the deposit. What a given * deposit reaches is decided by the debt it implies — * `debt = netValue x (leverage - 1)` — and by the `debtLimits` the market puts that * debt in. * * Synchronous, unlike the ceilings above it: those read the account from the * chain, this one only needs loaded market state, so a form can ask on every * keystroke. Opening values `collateral`; passing `position` selects adjust * mode, which derives own funds, debt and quota state from that position. * * Nothing at all when the market has no range to offer: a deposit too small * to carry `minDebt` at any leverage the threshold allows, or a manager with * no borrowing room left. Not the same answer as "every leverage works", and * a caller must not mark a range for it. **/ leverageBand(strategy: StrategyInput, collateral: readonly Asset[], targetHF?: Bps, position?: StrategyPosition): LeverageBand | undefined; /** * The collaterals an account can actually take out, most valuable first — * what a withdraw-collateral picker offers. * * `StrategyPosition.collaterals` is everything the account holds, in the * order the manager keeps its tokens. Phantoms are in there: the position * reports one as itself and puts the asset it redeems into under * `withdrawals`, and {@link withdrawCollateral} cannot move a balance that * is not transferable. Balances below dust are already gone — the position * drops them as it is built. * * Synchronous, like {@link leverageBand}: it reads loaded token metadata and * the position it was handed, so a form can ask on every render. Nothing is * quoted here — which of these the router can sell is a different question, * and the answer to it is a prepared operation. **/ withdrawableCollaterals(position: StrategyPosition): PositionCollateral[]; /** * Largest amount of one collateral {@link withdrawCollateral} can move out * while the account stays safely collateralised, in the token's units: the * remaining assets are weighed by their liquidation thresholds (quoted ones * capped by their quotas) and the target keeps covering what the debt still * requires. Zero debt frees the whole balance — the ceiling a * withdraw-collateral form should offer. * * Options name independent main and safe price health-factor thresholds in * basis points. The SDK defaults to the form thresholds and adds its margin. * * A bare read: it answers its number, and throws on an account or a chain * the SDK does not hold. **/ maxWithdrawCollateral(position: PositionInput, token: Address, options?: MaxWithdrawCollateralOptions): Promise; /** * Largest loan {@link borrow} can draw against a given collateral while the * account stays safely collateralised, in the payout token's units — the * ceiling a borrow form should offer. * * The loan leaves the account, so the collateral alone backs the debt and * the market weighs it at safe prices, under its liquidation threshold and * capped by the quota the borrow buys for it. The answer is then held to * what the market will actually lend: the pool's free liquidity, the * manager's own allowance and the facade's `maxDebt`. * * `targetHF` names the health factor to land at, in basis points; omitted, * the SDK holds it to the threshold a form would. * * Synchronous, like {@link leverageBand} and for the same reason: the * account does not exist yet, so there is nothing to read and a form can ask * on every keystroke. * * It is a ceiling and not a verdict: the facade's `minDebt` is a floor, and * holding the answer to it would tell a form `0` for collateral that does * carry a loan, only a smaller one than this market lends. So a Max offered * from here can still be refused by {@link borrow} with `debtOutOfRange`, * which names the floor the amount fell short of. * * `0n` where this market funds no loan of this shape at any size — a * collateral worth nothing at safe prices, a payout token equal to the * collateral, a market with nothing left to lend, or a manager the SDK does * not hold. Not the same as "any amount works", and a caller must not offer * a Max for it. **/ maxBorrow(strategy: StrategyInput, params: MaxBorrowParams): bigint; /** * The tail of a delayed route: claim the matured withdrawal, then whatever the * operation that requested it still owes — repaying debt and paying the wallet * out for a withdrawal, repaying alone for a deleveraging, selling the rest of * the account and settling the loan for an exit, nothing beyond the claim for * the rest. * * The route is requested by {@link withdrawStrategy} or * {@link adjustLeverage}, whose `delayed` branch is the transaction that * starts it; days later the redemption matures and this finishes it. Nothing * has to be kept on the client in between: the request writes the operation * into the withdrawal's `extraData`, and reading the claimable decodes it * back. * * Answers like the instant flows, so both halves are consumed the same way. * Reports `noRecordedIntent` when the claim names no operation to resume. * * A claim can settle only part of what was queued — a legacy Mellow * multivault hands over what it holds liquid and re-queues the rest — and then * the result serves that share and `remainder` says what is left, see * {@link FinalizeResult.remainder}. **/ finalize(position: PositionInput, params: FinalizeParams): Promise>>; } //#endregion export type { BorrowState, CreditAccountNotEmptyError, CreditAccountNotFoundError, ExecutionCost, LeverageBand, MultipleDelayedWithdrawalsError, NoDelayedRouteError, NoRecordedIntentError, NoStrategyTargetCollateralError, OperationState, PathLossRate, PoolOperationError, RouteErrors, UnexpectedFailureError, UnsupportedCollateralTokenError, UnsupportedTokenPairError, WithPartialState, WithdrawCeilings, WithdrawalInProgressError };