@gearbox-protocol/sdk 15.1.0-next.21 → 15.1.0-next.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/cjs/new-sdk/prepare/PrepareApi.js +4 -4
  2. package/dist/cjs/sdk/accounts/intents/index.js +57 -28
  3. package/dist/cjs/sdk/accounts/intents/plan.js +40 -2
  4. package/dist/cjs/sdk/accounts/intents/realize.js +22 -12
  5. package/dist/cjs/sdk/accounts/intents/tail.js +120 -0
  6. package/dist/cjs/sdk/accounts/intents/utils/index.js +1 -0
  7. package/dist/cjs/sdk/accounts/intents/utils/router-path.js +32 -0
  8. package/dist/cjs/sdk/market/oracle/PriceOracleBaseContract.js +11 -0
  9. package/dist/cjs/sdk/positions/PositionsService.js +22 -11
  10. package/dist/esm/new-sdk/prepare/PrepareApi.js +4 -4
  11. package/dist/esm/sdk/accounts/intents/index.js +58 -29
  12. package/dist/esm/sdk/accounts/intents/plan.js +40 -3
  13. package/dist/esm/sdk/accounts/intents/realize.js +22 -12
  14. package/dist/esm/sdk/accounts/intents/tail.js +118 -0
  15. package/dist/esm/sdk/accounts/intents/utils/index.js +2 -2
  16. package/dist/esm/sdk/accounts/intents/utils/router-path.js +32 -1
  17. package/dist/esm/sdk/market/oracle/PriceOracleBaseContract.js +11 -0
  18. package/dist/esm/sdk/positions/PositionsService.js +22 -11
  19. package/dist/types/new-sdk/prepare/types.d.ts +22 -8
  20. package/dist/types/sdk/accounts/intents/index.d.ts +13 -6
  21. package/dist/types/sdk/accounts/intents/plan.d.ts +18 -2
  22. package/dist/types/sdk/accounts/intents/realize.d.ts +7 -0
  23. package/dist/types/sdk/accounts/intents/tail.d.ts +52 -0
  24. package/dist/types/sdk/accounts/intents/types.d.ts +46 -10
  25. package/dist/types/sdk/accounts/intents/utils/index.d.ts +2 -2
  26. package/dist/types/sdk/accounts/intents/utils/router-path.d.ts +15 -1
  27. package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +4 -0
  28. package/dist/types/sdk/market/oracle/types.d.ts +9 -0
  29. package/package.json +1 -1
@@ -0,0 +1,52 @@
1
+ import { ClaimableWithdrawal } from "../withdrawal-compressor/types.js";
2
+ import { OnchainSDK } from "../../OnchainSDK.js";
3
+ import { CreditAccountSlice, DelayedStart, OperationState, ResumableIntent } from "./types.js";
4
+ import { AccountCalculatorOperation, StartDelayedWithdrawalOperation } from "./operations.js";
5
+ import "../../index.js";
6
+ import { AccountView, Step } from "./plan.js";
7
+ //#region src/sdk/accounts/intents/tail.d.ts
8
+ /**
9
+ * The second half of a delayed intent: the claim, then whatever the intent
10
+ * still owes.
11
+ *
12
+ * Shared by the two callers that need it and must not disagree — the tail as
13
+ * it is previewed days later against the account that really exists, and the
14
+ * tail as it is projected the moment the request is made.
15
+ */
16
+ declare function planTail(args: {
17
+ intent: ResumableIntent;
18
+ claimable: ClaimableWithdrawal;
19
+ view: AccountView;
20
+ }): Step[];
21
+ /**
22
+ * Where a delayed intent ends up, worked out at the moment it is started.
23
+ *
24
+ * A request is only half a withdrawal, so the state it lands in is not the
25
+ * answer to "what does this do to my position": the debt is still there, the
26
+ * payout has not been made, and the position sits in a phantom token. What the
27
+ * caller means is the far side — and that side can be walked now, because the
28
+ * request already fixes the claim it will be finished from.
29
+ *
30
+ * So the same tail {@link planTail} builds at claim time is built here against
31
+ * the account as the request leaves it, with the claim it is expected to bring,
32
+ * and walked by the same realiser — with one substitution: routed legs are
33
+ * priced by the oracle rather than the pathfinder, since the funds they trade
34
+ * do not exist yet and no calldata is being produced. The result is an
35
+ * estimate that the engine's guards are nevertheless applied to, so a request
36
+ * that would strand the account is refused before it is sent rather than
37
+ * discovered days later.
38
+ */
39
+ declare function projectTail(args: {
40
+ /** The request as realised: the source spent, the phantom it produced. */
41
+ request: StartDelayedWithdrawalOperation;
42
+ delayed: DelayedStart;
43
+ /** The account the request was previewed against, for masks and market. */
44
+ creditAccount: CreditAccountSlice;
45
+ sdk: OnchainSDK;
46
+ quotaReserve: number | undefined;
47
+ }): Promise<{
48
+ state: OperationState;
49
+ operations: AccountCalculatorOperation[];
50
+ }>;
51
+ //#endregion
52
+ export { planTail, projectTail };
@@ -81,7 +81,11 @@ interface OperationState {
81
81
  type PreviewErrorReason = "debtOutOfRange" | "leverageOutOfRange" | "insufficientSourceBalance" |
82
82
  /** Input token is not accepted by the flow (e.g. deposit of a non-underlying). */
83
83
  "unsupportedCollateralToken" |
84
- /** No pool route between the requested pair, or several and none was picked. */
84
+ /**
85
+ * No route for the trade the plan needs: no pool pair between the tokens
86
+ * requested, several and none was picked, or the pathfinder itself found no
87
+ * path for the amounts involved.
88
+ */
85
89
  "unsupportedTokenPair" |
86
90
  /**
87
91
  * The intent cannot settle with a delay: the source has no redemption config,
@@ -93,9 +97,8 @@ type PreviewErrorReason = "debtOutOfRange" | "leverageOutOfRange" | "insufficien
93
97
  /** A redemption of the same asset is already in flight. */
94
98
  "withdrawalInProgress" |
95
99
  /**
96
- * The claim names no operation to resume: requested without an intent, read
97
- * through a compressor too old to report one, or a full close, which the
98
- * engine no longer previews.
100
+ * The claim names no operation to resume: requested without an intent, or
101
+ * read through a compressor too old to report one.
99
102
  */
100
103
  "noRecordedIntent" |
101
104
  /** The facade or the pool behind it is paused: nothing can be done at all. */
@@ -146,10 +149,44 @@ interface DelayedStart {
146
149
  * instead, which settles all of it in one transaction.
147
150
  */
148
151
  settlement: "instant" | "delayed";
152
+ /**
153
+ * What the claim is expected to credit the account with once the redemption
154
+ * matures: the venue's payout token and the amount the request queued.
155
+ * `undefined` when the request settled on the spot and nothing is coming.
156
+ *
157
+ * An estimate, not a quote — the issuer prices the redemption when it pays
158
+ * out, and the state the intent is previewed against was read now.
159
+ */
160
+ claim: {
161
+ token: Address;
162
+ amount: bigint;
163
+ } | undefined;
164
+ /**
165
+ * The account as the request transaction alone leaves it: the source spent,
166
+ * the phantom of the in-flight redemption in its place, the debt untouched.
167
+ *
168
+ * This is the state the facade judges when the transaction lands, so it is
169
+ * the one the engine's guards are applied to — while the `preview` beside it
170
+ * is where the intent ends up, tail included, which is what a caller asking
171
+ * "what does this do to my position" means.
172
+ */
173
+ afterRequest: OperationState;
149
174
  }
150
175
  /**
151
176
  * What the leading half of a delayed intent yields: the request transaction,
152
177
  * plus what it recorded for the tail.
178
+ *
179
+ * `operations` and `calls` are the request and nothing else — that is the only
180
+ * transaction there is to send now. `preview`, though, is where the intent
181
+ * ends: the state the account reaches once the redemption matures, is claimed
182
+ * and the tail runs, since that is what the caller asked for when they asked
183
+ * to withdraw. The half-way state the request itself lands in is
184
+ * {@link DelayedStart.afterRequest}, and both are validated before either is
185
+ * reported.
186
+ *
187
+ * The tail is projected from oracle prices rather than from a route — the funds
188
+ * it trades do not exist yet — so its half of the numbers is an estimate. What
189
+ * the transaction on offer does is not.
153
190
  */
154
191
  type DelayedStartResult = {
155
192
  ok: true;
@@ -406,14 +443,13 @@ type StartIntent = AddCollateralIntent | WithdrawAssetIntent | AdjustLeverageInt
406
443
  */
407
444
  type DelayableIntent = AdjustLeverageIntent | WithdrawStrategyIntent;
408
445
  /**
409
- * A delayed intent this engine knows how to finish.
446
+ * A delayed intent this engine knows how to finish — every one of them.
410
447
  *
411
- * `CLOSE_ACCOUNT` is absent on purpose: closing goes through the facade's own
412
- * entry point, which this engine no longer builds.
448
+ * `CLOSE_ACCOUNT` included: an exit is a plain multicall like any other
449
+ * operation here (sell everything, settle the loan, hand the rest over), not
450
+ * the facade's own close entry point, so the engine can build its tail too.
413
451
  */
414
- type ResumableIntent = Exclude<DelayedIntent, {
415
- type: "CLOSE_ACCOUNT";
416
- }>;
452
+ type ResumableIntent = DelayedIntent;
417
453
  /** Shared inputs plus the matured withdrawal the tail is built around. */
418
454
  type FinishIntentProps = StartIntentProps & {
419
455
  intent: ResumableIntent;
@@ -1,4 +1,5 @@
1
1
  import { fetchCreditAccountSlice, toCreditAccountSlice } from "./credit-account-slice.js";
2
+ import { OpenStrategyLeg, RouterPaths, SwapLeg, createOraclePaths, createRouterPaths } from "./router-path.js";
2
3
  import { adjustStateToSnapshot } from "./adjust-state-to-snapshot.js";
3
4
  import { assembleOperationCalls } from "./assemble-operation-calls.js";
4
5
  import { calcBorrowedAmountPlusInterestAndFees } from "./borrowed-amount-plus-interest-and-fees.js";
@@ -7,5 +8,4 @@ import { convertAmount } from "./convert-amount.js";
7
8
  import { ConvertFn, LedgerSnapshot, OperationLedger } from "./ledger.js";
8
9
  import { CandidateToken, isPhantomToken, isRedemptionPhantomToken, pickFattestNonPhantomToken, rankAccountTokens } from "./pick-token.js";
9
10
  import { clearedQuotas, getQuotasForUpdate, quotasAfterUpdate } from "./quotas-for-update.js";
10
- import { OpenStrategyLeg, RouterPaths, SwapLeg, createRouterPaths } from "./router-path.js";
11
- export { CandidateToken, ConvertFn, LedgerSnapshot, OpenStrategyLeg, OperationLedger, RouterPaths, SwapLeg, adjustStateToSnapshot, assembleOperationCalls, calcBorrowedAmountPlusInterestAndFees, clearedQuotas, convertAmount, createRouterPaths, eq, fetchCreditAccountSlice, getQuotasForUpdate, isPhantomToken, isRedemptionPhantomToken, pickFattestNonPhantomToken, quotasAfterUpdate, rankAccountTokens, toCreditAccountSlice, toRouterCaSlice, toTargetDecimals };
11
+ export { CandidateToken, ConvertFn, LedgerSnapshot, OpenStrategyLeg, OperationLedger, RouterPaths, SwapLeg, adjustStateToSnapshot, assembleOperationCalls, calcBorrowedAmountPlusInterestAndFees, clearedQuotas, convertAmount, createOraclePaths, createRouterPaths, eq, fetchCreditAccountSlice, getQuotasForUpdate, isPhantomToken, isRedemptionPhantomToken, pickFattestNonPhantomToken, quotasAfterUpdate, rankAccountTokens, toCreditAccountSlice, toRouterCaSlice, toTargetDecimals };
@@ -66,5 +66,19 @@ declare function createRouterPaths(args: {
66
66
  creditAccount: CreditAccountSlice;
67
67
  slippage: number;
68
68
  }): RouterPaths;
69
+ /**
70
+ * The same door, priced by the oracle and opening onto no calldata.
71
+ *
72
+ * For a leg that cannot be quoted yet: the tail of a redemption trades funds
73
+ * that do not exist, along a route the pathfinder will only be able to build
74
+ * once they do. Asking it now would price a swap of nothing, so the amounts
75
+ * come from the oracle instead — an estimate with no slippage floor, which is
76
+ * all a projection days out can honestly be — and the walk yields a state
77
+ * rather than a transaction.
78
+ */
79
+ declare function createOraclePaths(args: {
80
+ sdk: OnchainSDK;
81
+ creditAccount: CreditAccountSlice;
82
+ }): RouterPaths;
69
83
  //#endregion
70
- export { OpenStrategyLeg, RouterPaths, SwapLeg, createRouterPaths };
84
+ export { OpenStrategyLeg, RouterPaths, SwapLeg, createOraclePaths, createRouterPaths };
@@ -92,6 +92,10 @@ declare abstract class PriceOracleBaseContract<abi extends Abi | readonly unknow
92
92
  * {@inheritDoc IPriceOracleContract.convertFromUSD}
93
93
  **/
94
94
  convertFromUSD(to: Address, amount: bigint, reserve?: boolean): bigint;
95
+ /**
96
+ * {@inheritDoc IPriceOracleContract.safeConvert}
97
+ **/
98
+ safeConvert(from: Address, to: Address, amount: bigint): bigint | null;
95
99
  /**
96
100
  * {@inheritDoc IPriceOracleContract.safeConvertToUSD}
97
101
  **/
@@ -131,6 +131,15 @@ interface IPriceOracleContract extends IBaseContract {
131
131
  * @param reserve - Use reserve feeds instead of main.
132
132
  **/
133
133
  convert: (from: Address, to: Address, amount: bigint, reserve?: boolean) => bigint;
134
+ /**
135
+ * Like {@link convert}, but returns `null` instead of throwing when either
136
+ * token cannot be priced (missing or unsuccessful feed).
137
+ *
138
+ * @param from - Source token address.
139
+ * @param to - Destination token address.
140
+ * @param amount - Amount in source-token decimals.
141
+ **/
142
+ safeConvert: (from: Address, to: Address, amount: bigint) => bigint | null;
134
143
  /**
135
144
  * Converts a token amount to its USD value using latest known prices.
136
145
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "15.1.0-next.21",
3
+ "version": "15.1.0-next.23",
4
4
  "description": "Gearbox SDK",
5
5
  "license": "MIT",
6
6
  "repository": {