@defisaver/positions-sdk 2.1.127-midnight-13-dev → 2.1.127-midnight-14-dev

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.
@@ -64,7 +64,6 @@ export interface MorphoMidnightPaybackUnitsQuote {
64
64
  * Rounded **down**, since a wider slippage is a looser cap than the caller asked for.
65
65
  */
66
66
  export declare const midnightSlippageParam: (slippagePercent: Dec.Value) => string;
67
- export declare const morphoMidnightMarketReportsBorrowInfo: (market: Pick<MorphoMidnightMarketData, "curator"> | string) => boolean;
68
67
  /**
69
68
  * Current borrower rate + debt breakdown from the Midnight positions API. Reconstructing this from the raw
70
69
  * `/transactions` fill history only sums `borrow` fills, so it overstates debt for any position with an
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getMorphoMidnightPaybackUnitsQuote = exports.getMorphoMidnightPaybackQuote = exports.getMorphoMidnightBorrowQuote = exports.getMorphoMidnightMarketBook = exports.scaleMorphoMidnightDebtSplit = exports.getMorphoMidnightUserBorrowInfo = exports.morphoMidnightMarketReportsBorrowInfo = exports.midnightSlippageParam = exports.getMorphoMidnightAggregatedPositionData = exports.tenorOfferToApiOffer = exports.tenorOfferFillToApiFill = exports.tenorBookRateToApyPercent = exports.tenorBookKeyFor = exports.MIDNIGHT_DEFAULT_RATE_SLIPPAGE = exports.midnightTimeToMaturityDays = exports.midnightPriceFromApy = exports.midnightBoundPrice = exports.midnightBookBestFirst = exports.midnightApyFromPrice = exports.buildMidnightParsedBook = void 0;
15
+ exports.getMorphoMidnightPaybackUnitsQuote = exports.getMorphoMidnightPaybackQuote = exports.getMorphoMidnightBorrowQuote = exports.getMorphoMidnightMarketBook = exports.scaleMorphoMidnightDebtSplit = exports.getMorphoMidnightUserBorrowInfo = exports.midnightSlippageParam = exports.getMorphoMidnightAggregatedPositionData = exports.tenorOfferToApiOffer = exports.tenorOfferFillToApiFill = exports.tenorBookRateToApyPercent = exports.tenorBookKeyFor = exports.MIDNIGHT_DEFAULT_RATE_SLIPPAGE = exports.midnightTimeToMaturityDays = exports.midnightPriceFromApy = exports.midnightBoundPrice = exports.midnightBookBestFirst = exports.midnightApyFromPrice = exports.buildMidnightParsedBook = void 0;
16
16
  const decimal_js_1 = __importDefault(require("decimal.js"));
17
17
  const tokens_1 = require("@defisaver/tokens");
18
18
  const moneymarket_1 = require("../../moneymarket");
@@ -123,8 +123,6 @@ const MIDNIGHT_SLIPPAGE_MAX = 100;
123
123
  */
124
124
  const midnightSlippageParam = (slippagePercent) => decimal_js_1.default.min(decimal_js_1.default.max(new decimal_js_1.default(slippagePercent), MIDNIGHT_SLIPPAGE_MIN), MIDNIGHT_SLIPPAGE_MAX).toDP(1, decimal_js_1.default.ROUND_DOWN).toString();
125
125
  exports.midnightSlippageParam = midnightSlippageParam;
126
- const morphoMidnightMarketReportsBorrowInfo = (market) => (!(0, morphoMidnight_1.isTenorMidnightMarket)(market));
127
- exports.morphoMidnightMarketReportsBorrowInfo = morphoMidnightMarketReportsBorrowInfo;
128
126
  /**
129
127
  * Current borrower rate + debt breakdown from the Midnight positions API. Reconstructing this from the raw
130
128
  * `/transactions` fill history only sums `borrow` fills, so it overstates debt for any position with an
@@ -169,35 +169,32 @@ function _getMorphoMidnightAccountData(provider, network, account, selectedMarke
169
169
  let borrowInfoStatus = types_1.MorphoMidnightBorrowInfoStatus.Available;
170
170
  let assetsDataForApy = marketInfo.assetsData;
171
171
  if (new decimal_js_1.default(positionInfo.debt.toString()).gt(0)) {
172
- if (!(0, morphoMidnightHelpers_1.morphoMidnightMarketReportsBorrowInfo)(selectedMarket)) {
173
- borrowInfoStatus = types_1.MorphoMidnightBorrowInfoStatus.Unavailable;
174
- }
175
- else {
176
- try {
177
- const borrowInfo = yield (0, morphoMidnightHelpers_1.getMorphoMidnightUserBorrowInfo)(account, marketId, marketInfo.loanToken);
178
- if (new decimal_js_1.default(borrowInfo.debtTotal).gt(0)) {
179
- borrowRate = borrowInfo.borrowRate;
180
- debtBase = borrowInfo.debtBase;
181
- debtInterest = borrowInfo.debtInterest;
182
- usedAssets[marketInfo.loanToken].borrowRate = borrowRate;
183
- // Reflect the real borrow cost in netApy without mutating the shared marketInfo.assetsData.
184
- assetsDataForApy = Object.assign(Object.assign({}, marketInfo.assetsData), { [marketInfo.loanToken]: Object.assign(Object.assign({}, loanTokenData), { borrowRate }) });
185
- const describesChainDebt = new decimal_js_1.default(borrowInfo.debtTotal).eq(debt);
186
- const ratePriced = new decimal_js_1.default(borrowRate).gt(0) || new decimal_js_1.default(debtInterest).lte(0);
187
- borrowInfoStatus = describesChainDebt && ratePriced
188
- ? types_1.MorphoMidnightBorrowInfoStatus.Available
189
- : types_1.MorphoMidnightBorrowInfoStatus.Pending;
190
- }
191
- else {
192
- // No entry for the position: the API does not know it yet, rather than it having no principal.
193
- borrowInfoStatus = types_1.MorphoMidnightBorrowInfoStatus.Pending;
194
- }
172
+ try {
173
+ // Curator-agnostic: `/users/:account/positions` is indexed off the Midnight singleton, so it carries
174
+ // Tenor-curated markets too. Only the *book* differs by curator, and that is quoted elsewhere.
175
+ const borrowInfo = yield (0, morphoMidnightHelpers_1.getMorphoMidnightUserBorrowInfo)(account, marketId, marketInfo.loanToken);
176
+ if (new decimal_js_1.default(borrowInfo.debtTotal).gt(0)) {
177
+ borrowRate = borrowInfo.borrowRate;
178
+ debtBase = borrowInfo.debtBase;
179
+ debtInterest = borrowInfo.debtInterest;
180
+ usedAssets[marketInfo.loanToken].borrowRate = borrowRate;
181
+ // Reflect the real borrow cost in netApy without mutating the shared marketInfo.assetsData.
182
+ assetsDataForApy = Object.assign(Object.assign({}, marketInfo.assetsData), { [marketInfo.loanToken]: Object.assign(Object.assign({}, loanTokenData), { borrowRate }) });
183
+ const describesChainDebt = new decimal_js_1.default(borrowInfo.debtTotal).eq(debt);
184
+ const ratePriced = new decimal_js_1.default(borrowRate).gt(0) || new decimal_js_1.default(debtInterest).lte(0);
185
+ borrowInfoStatus = describesChainDebt && ratePriced
186
+ ? types_1.MorphoMidnightBorrowInfoStatus.Available
187
+ : types_1.MorphoMidnightBorrowInfoStatus.Pending;
195
188
  }
196
- catch (err) {
197
- // Positions API unreachable the fallback above still renders, and the next call may succeed.
189
+ else {
190
+ // No entry for the position: the API does not know it yet, rather than it having no principal.
198
191
  borrowInfoStatus = types_1.MorphoMidnightBorrowInfoStatus.Pending;
199
192
  }
200
193
  }
194
+ catch (err) {
195
+ // Positions API unreachable — the fallback above still renders, and the next call may succeed.
196
+ borrowInfoStatus = types_1.MorphoMidnightBorrowInfoStatus.Pending;
197
+ }
201
198
  }
202
199
  return Object.assign({ usedAssets,
203
200
  credit,
@@ -123,13 +123,10 @@ export interface MorphoMidnightAggregatedPositionData {
123
123
  * - `Pending` — the indexer has not caught up with the chain yet: it does not know the position, or its
124
124
  * split describes a different debt. Refetching resolves it; `getMorphoMidnightUserBorrowInfo` failing
125
125
  * outright lands here too, since the next call may well succeed.
126
- * - `Unavailable` — no source covers this market, so refetching changes nothing. See
127
- * `morphoMidnightMarketReportsBorrowInfo`.
128
126
  */
129
127
  export declare enum MorphoMidnightBorrowInfoStatus {
130
128
  Available = "available",
131
- Pending = "pending",
132
- Unavailable = "unavailable"
129
+ Pending = "pending"
133
130
  }
134
131
  export interface MorphoMidnightPositionData extends MorphoMidnightAggregatedPositionData {
135
132
  usedAssets: MMUsedAssets;
@@ -39,12 +39,9 @@ var MorphoMidnightVersions;
39
39
  * - `Pending` — the indexer has not caught up with the chain yet: it does not know the position, or its
40
40
  * split describes a different debt. Refetching resolves it; `getMorphoMidnightUserBorrowInfo` failing
41
41
  * outright lands here too, since the next call may well succeed.
42
- * - `Unavailable` — no source covers this market, so refetching changes nothing. See
43
- * `morphoMidnightMarketReportsBorrowInfo`.
44
42
  */
45
43
  var MorphoMidnightBorrowInfoStatus;
46
44
  (function (MorphoMidnightBorrowInfoStatus) {
47
45
  MorphoMidnightBorrowInfoStatus["Available"] = "available";
48
46
  MorphoMidnightBorrowInfoStatus["Pending"] = "pending";
49
- MorphoMidnightBorrowInfoStatus["Unavailable"] = "unavailable";
50
47
  })(MorphoMidnightBorrowInfoStatus || (exports.MorphoMidnightBorrowInfoStatus = MorphoMidnightBorrowInfoStatus = {}));
@@ -64,7 +64,6 @@ export interface MorphoMidnightPaybackUnitsQuote {
64
64
  * Rounded **down**, since a wider slippage is a looser cap than the caller asked for.
65
65
  */
66
66
  export declare const midnightSlippageParam: (slippagePercent: Dec.Value) => string;
67
- export declare const morphoMidnightMarketReportsBorrowInfo: (market: Pick<MorphoMidnightMarketData, "curator"> | string) => boolean;
68
67
  /**
69
68
  * Current borrower rate + debt breakdown from the Midnight positions API. Reconstructing this from the raw
70
69
  * `/transactions` fill history only sums `borrow` fills, so it overstates debt for any position with an
@@ -104,7 +104,6 @@ const MIDNIGHT_SLIPPAGE_MAX = 100;
104
104
  * Rounded **down**, since a wider slippage is a looser cap than the caller asked for.
105
105
  */
106
106
  export const midnightSlippageParam = (slippagePercent) => Dec.min(Dec.max(new Dec(slippagePercent), MIDNIGHT_SLIPPAGE_MIN), MIDNIGHT_SLIPPAGE_MAX).toDP(1, Dec.ROUND_DOWN).toString();
107
- export const morphoMidnightMarketReportsBorrowInfo = (market) => (!isTenorMidnightMarket(market));
108
107
  /**
109
108
  * Current borrower rate + debt breakdown from the Midnight positions API. Reconstructing this from the raw
110
109
  * `/transactions` fill history only sums `borrow` fills, so it overstates debt for any position with an
@@ -15,7 +15,7 @@ import { MorphoMidnightBorrowInfoStatus, } from '../types';
15
15
  import { USD_QUOTE } from '../constants';
16
16
  import { calculateNetApy } from '../staking';
17
17
  import { isMainnetNetwork, wethToEth } from '../services/utils';
18
- import { getMorphoMidnightAggregatedPositionData, getMorphoMidnightUserBorrowInfo, morphoMidnightMarketReportsBorrowInfo } from '../helpers/morphoMidnightHelpers';
18
+ import { getMorphoMidnightAggregatedPositionData, getMorphoMidnightUserBorrowInfo } from '../helpers/morphoMidnightHelpers';
19
19
  import { getChainlinkAssetAddress } from '../services/priceService';
20
20
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
21
21
  const HARDCODED_USD_STABLE_PRICE = '100000000'; // $1 with 8 decimals
@@ -158,35 +158,32 @@ export function _getMorphoMidnightAccountData(provider, network, account, select
158
158
  let borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Available;
159
159
  let assetsDataForApy = marketInfo.assetsData;
160
160
  if (new Dec(positionInfo.debt.toString()).gt(0)) {
161
- if (!morphoMidnightMarketReportsBorrowInfo(selectedMarket)) {
162
- borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Unavailable;
163
- }
164
- else {
165
- try {
166
- const borrowInfo = yield getMorphoMidnightUserBorrowInfo(account, marketId, marketInfo.loanToken);
167
- if (new Dec(borrowInfo.debtTotal).gt(0)) {
168
- borrowRate = borrowInfo.borrowRate;
169
- debtBase = borrowInfo.debtBase;
170
- debtInterest = borrowInfo.debtInterest;
171
- usedAssets[marketInfo.loanToken].borrowRate = borrowRate;
172
- // Reflect the real borrow cost in netApy without mutating the shared marketInfo.assetsData.
173
- assetsDataForApy = Object.assign(Object.assign({}, marketInfo.assetsData), { [marketInfo.loanToken]: Object.assign(Object.assign({}, loanTokenData), { borrowRate }) });
174
- const describesChainDebt = new Dec(borrowInfo.debtTotal).eq(debt);
175
- const ratePriced = new Dec(borrowRate).gt(0) || new Dec(debtInterest).lte(0);
176
- borrowInfoStatus = describesChainDebt && ratePriced
177
- ? MorphoMidnightBorrowInfoStatus.Available
178
- : MorphoMidnightBorrowInfoStatus.Pending;
179
- }
180
- else {
181
- // No entry for the position: the API does not know it yet, rather than it having no principal.
182
- borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Pending;
183
- }
161
+ try {
162
+ // Curator-agnostic: `/users/:account/positions` is indexed off the Midnight singleton, so it carries
163
+ // Tenor-curated markets too. Only the *book* differs by curator, and that is quoted elsewhere.
164
+ const borrowInfo = yield getMorphoMidnightUserBorrowInfo(account, marketId, marketInfo.loanToken);
165
+ if (new Dec(borrowInfo.debtTotal).gt(0)) {
166
+ borrowRate = borrowInfo.borrowRate;
167
+ debtBase = borrowInfo.debtBase;
168
+ debtInterest = borrowInfo.debtInterest;
169
+ usedAssets[marketInfo.loanToken].borrowRate = borrowRate;
170
+ // Reflect the real borrow cost in netApy without mutating the shared marketInfo.assetsData.
171
+ assetsDataForApy = Object.assign(Object.assign({}, marketInfo.assetsData), { [marketInfo.loanToken]: Object.assign(Object.assign({}, loanTokenData), { borrowRate }) });
172
+ const describesChainDebt = new Dec(borrowInfo.debtTotal).eq(debt);
173
+ const ratePriced = new Dec(borrowRate).gt(0) || new Dec(debtInterest).lte(0);
174
+ borrowInfoStatus = describesChainDebt && ratePriced
175
+ ? MorphoMidnightBorrowInfoStatus.Available
176
+ : MorphoMidnightBorrowInfoStatus.Pending;
184
177
  }
185
- catch (err) {
186
- // Positions API unreachable the fallback above still renders, and the next call may succeed.
178
+ else {
179
+ // No entry for the position: the API does not know it yet, rather than it having no principal.
187
180
  borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Pending;
188
181
  }
189
182
  }
183
+ catch (err) {
184
+ // Positions API unreachable — the fallback above still renders, and the next call may succeed.
185
+ borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Pending;
186
+ }
190
187
  }
191
188
  return Object.assign({ usedAssets,
192
189
  credit,
@@ -123,13 +123,10 @@ export interface MorphoMidnightAggregatedPositionData {
123
123
  * - `Pending` — the indexer has not caught up with the chain yet: it does not know the position, or its
124
124
  * split describes a different debt. Refetching resolves it; `getMorphoMidnightUserBorrowInfo` failing
125
125
  * outright lands here too, since the next call may well succeed.
126
- * - `Unavailable` — no source covers this market, so refetching changes nothing. See
127
- * `morphoMidnightMarketReportsBorrowInfo`.
128
126
  */
129
127
  export declare enum MorphoMidnightBorrowInfoStatus {
130
128
  Available = "available",
131
- Pending = "pending",
132
- Unavailable = "unavailable"
129
+ Pending = "pending"
133
130
  }
134
131
  export interface MorphoMidnightPositionData extends MorphoMidnightAggregatedPositionData {
135
132
  usedAssets: MMUsedAssets;
@@ -36,12 +36,9 @@ export var MorphoMidnightVersions;
36
36
  * - `Pending` — the indexer has not caught up with the chain yet: it does not know the position, or its
37
37
  * split describes a different debt. Refetching resolves it; `getMorphoMidnightUserBorrowInfo` failing
38
38
  * outright lands here too, since the next call may well succeed.
39
- * - `Unavailable` — no source covers this market, so refetching changes nothing. See
40
- * `morphoMidnightMarketReportsBorrowInfo`.
41
39
  */
42
40
  export var MorphoMidnightBorrowInfoStatus;
43
41
  (function (MorphoMidnightBorrowInfoStatus) {
44
42
  MorphoMidnightBorrowInfoStatus["Available"] = "available";
45
43
  MorphoMidnightBorrowInfoStatus["Pending"] = "pending";
46
- MorphoMidnightBorrowInfoStatus["Unavailable"] = "unavailable";
47
44
  })(MorphoMidnightBorrowInfoStatus || (MorphoMidnightBorrowInfoStatus = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.127-midnight-13-dev",
3
+ "version": "2.1.127-midnight-14-dev",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -227,10 +227,6 @@ export const midnightSlippageParam = (slippagePercent: Dec.Value): string => Dec
227
227
  MIDNIGHT_SLIPPAGE_MAX,
228
228
  ).toDP(1, Dec.ROUND_DOWN).toString();
229
229
 
230
- export const morphoMidnightMarketReportsBorrowInfo = (market: Pick<MorphoMidnightMarketData, 'curator'> | string): boolean => (
231
- !isTenorMidnightMarket(market)
232
- );
233
-
234
230
  /**
235
231
  * Current borrower rate + debt breakdown from the Midnight positions API. Reconstructing this from the raw
236
232
  * `/transactions` fill history only sums `borrow` fills, so it overstates debt for any position with an
@@ -13,7 +13,7 @@ import {
13
13
  import { USD_QUOTE } from '../constants';
14
14
  import { calculateNetApy } from '../staking';
15
15
  import { isMainnetNetwork, wethToEth } from '../services/utils';
16
- import { getMorphoMidnightAggregatedPositionData, getMorphoMidnightUserBorrowInfo, morphoMidnightMarketReportsBorrowInfo } from '../helpers/morphoMidnightHelpers';
16
+ import { getMorphoMidnightAggregatedPositionData, getMorphoMidnightUserBorrowInfo } from '../helpers/morphoMidnightHelpers';
17
17
  import { getChainlinkAssetAddress } from '../services/priceService';
18
18
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
19
19
 
@@ -166,34 +166,32 @@ export async function _getMorphoMidnightAccountData(provider: Client, network: N
166
166
  let borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Available;
167
167
  let assetsDataForApy = marketInfo.assetsData;
168
168
  if (new Dec(positionInfo.debt.toString()).gt(0)) {
169
- if (!morphoMidnightMarketReportsBorrowInfo(selectedMarket)) {
170
- borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Unavailable;
171
- } else {
172
- try {
173
- const borrowInfo = await getMorphoMidnightUserBorrowInfo(account, marketId, marketInfo.loanToken);
174
- if (new Dec(borrowInfo.debtTotal).gt(0)) {
175
- borrowRate = borrowInfo.borrowRate;
176
- debtBase = borrowInfo.debtBase;
177
- debtInterest = borrowInfo.debtInterest;
178
- usedAssets[marketInfo.loanToken].borrowRate = borrowRate;
179
- // Reflect the real borrow cost in netApy without mutating the shared marketInfo.assetsData.
180
- assetsDataForApy = {
181
- ...marketInfo.assetsData,
182
- [marketInfo.loanToken]: { ...loanTokenData, borrowRate },
183
- };
184
- const describesChainDebt = new Dec(borrowInfo.debtTotal).eq(debt);
185
- const ratePriced = new Dec(borrowRate).gt(0) || new Dec(debtInterest).lte(0);
186
- borrowInfoStatus = describesChainDebt && ratePriced
187
- ? MorphoMidnightBorrowInfoStatus.Available
188
- : MorphoMidnightBorrowInfoStatus.Pending;
189
- } else {
190
- // No entry for the position: the API does not know it yet, rather than it having no principal.
191
- borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Pending;
192
- }
193
- } catch (err) {
194
- // Positions API unreachable — the fallback above still renders, and the next call may succeed.
169
+ try {
170
+ // Curator-agnostic: `/users/:account/positions` is indexed off the Midnight singleton, so it carries
171
+ // Tenor-curated markets too. Only the *book* differs by curator, and that is quoted elsewhere.
172
+ const borrowInfo = await getMorphoMidnightUserBorrowInfo(account, marketId, marketInfo.loanToken);
173
+ if (new Dec(borrowInfo.debtTotal).gt(0)) {
174
+ borrowRate = borrowInfo.borrowRate;
175
+ debtBase = borrowInfo.debtBase;
176
+ debtInterest = borrowInfo.debtInterest;
177
+ usedAssets[marketInfo.loanToken].borrowRate = borrowRate;
178
+ // Reflect the real borrow cost in netApy without mutating the shared marketInfo.assetsData.
179
+ assetsDataForApy = {
180
+ ...marketInfo.assetsData,
181
+ [marketInfo.loanToken]: { ...loanTokenData, borrowRate },
182
+ };
183
+ const describesChainDebt = new Dec(borrowInfo.debtTotal).eq(debt);
184
+ const ratePriced = new Dec(borrowRate).gt(0) || new Dec(debtInterest).lte(0);
185
+ borrowInfoStatus = describesChainDebt && ratePriced
186
+ ? MorphoMidnightBorrowInfoStatus.Available
187
+ : MorphoMidnightBorrowInfoStatus.Pending;
188
+ } else {
189
+ // No entry for the position: the API does not know it yet, rather than it having no principal.
195
190
  borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Pending;
196
191
  }
192
+ } catch (err) {
193
+ // Positions API unreachable — the fallback above still renders, and the next call may succeed.
194
+ borrowInfoStatus = MorphoMidnightBorrowInfoStatus.Pending;
197
195
  }
198
196
  }
199
197
 
@@ -142,13 +142,10 @@ export interface MorphoMidnightAggregatedPositionData {
142
142
  * - `Pending` — the indexer has not caught up with the chain yet: it does not know the position, or its
143
143
  * split describes a different debt. Refetching resolves it; `getMorphoMidnightUserBorrowInfo` failing
144
144
  * outright lands here too, since the next call may well succeed.
145
- * - `Unavailable` — no source covers this market, so refetching changes nothing. See
146
- * `morphoMidnightMarketReportsBorrowInfo`.
147
145
  */
148
146
  export enum MorphoMidnightBorrowInfoStatus {
149
147
  Available = 'available',
150
148
  Pending = 'pending',
151
- Unavailable = 'unavailable',
152
149
  }
153
150
 
154
151
  // Fixed-rate/YTM (derived from entry price + orderbook) is intentionally absent in MVP: