@1delta/margin-fetcher 0.0.412 → 0.0.413

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.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { PublicClient, Address, Hex } from 'viem';
2
2
  import { Lender } from '@1delta/lender-registry';
3
- export { isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
3
+ export { hasCrossMarginRisk, isAaveType, isAaveV2Type, isAaveV32Type, isAaveV3Type, isCompoundV3, isCompoundV3Type, isInit, isMorphoType, isMultiMarket, isYLDR } from '@1delta/lender-registry';
4
4
  import { DebitData, LenderDebitData, LstAcceptedInput } from '@1delta/calldata-sdk';
5
5
  import { RelayProxyConfig } from '@1delta/proxy-fetch';
6
6
  import { TermMarketConfig, LiquityBranchConfig, LiquityConfigChain, RiverMarketConfig, RiverConfigChain, RiverChainData, InverseMarketConfig, InverseConfigChain, InverseChainData, ResupplyConfigChain, LlamaLendMarketConfig, LlamaLendConfigChain, LlamaLendChainData, UsddMarketConfig, UsddConfigChain, UsddChainData, FrankencoinMarketConfig, FrankencoinConfigChain, FrankencoinChainData, TellerPoolConfig, MorphoTypeVaultEntry } from '@1delta/data-sdk';
@@ -787,6 +787,38 @@ declare function createRawRpcCalls(preparedCalls: PreparedCall[], batchSize?: nu
787
787
  declare function createMulticallRpcCall(preparedCalls: PreparedCall[], multicallAddress: string, batchSize?: number, blockTag?: string, allowFailure?: boolean): MulticallRpcBatch[];
788
788
 
789
789
  type Call = GeneralCall;
790
+ /**
791
+ * Sentinel written into the result array for a call that returned NO data —
792
+ * a revert, an RPC error, or a whole `aggregate3` chunk that was rejected
793
+ * (rate limit, subrequest cap, dropped connection: viem marks every call in a
794
+ * rejected chunk as `status: 'failure'`).
795
+ *
796
+ * It is NOT a zero value. Parsers must skip these slots — coercing one to `0`
797
+ * turns a failed read into a phantom "no balance" position and, worse, makes a
798
+ * real deposit or debt silently disappear from a user's portfolio.
799
+ */
800
+ declare const MULTICALL_FAILURE = "0x";
801
+ /** True when a multicall slot holds no usable data (see {@link MULTICALL_FAILURE}). */
802
+ declare const isFailedCall: (value: unknown) => boolean;
803
+ /** Reported for each endpoint that failed to serve a batch. */
804
+ interface EndpointFailure {
805
+ chainId: string;
806
+ /** Endpoint URL, or `rpc#<id>` when the transport does not expose one. */
807
+ url: string;
808
+ rpcId: number;
809
+ /** `transport` — the request itself died. `slots` — it answered with nothing but failures. */
810
+ kind: 'transport' | 'slots';
811
+ }
812
+ interface MulticallEndpointOptions {
813
+ /**
814
+ * Endpoint URLs already attempted for this call set. Failover consults it so
815
+ * a retry lands on an endpoint that has NOT already failed — see
816
+ * {@link resolveEndpoint}.
817
+ */
818
+ tried?: Set<string>;
819
+ /** Invoked for every endpoint that fails, so callers can demote it. */
820
+ onEndpointFailure?: (info: EndpointFailure) => void;
821
+ }
790
822
  declare function prepareMulticallInputs(abi: any[], calls: Call[]): PreparedCall[];
791
823
 
792
824
  interface PreparedUserDataRpcCalls {
@@ -1049,33 +1081,106 @@ type UserData = {
1049
1081
  * not as the user's full position.
1050
1082
  */
1051
1083
  incomplete?: boolean;
1084
+ /**
1085
+ * Set when this entry did NOT come from the current read: the live read failed
1086
+ * and a previously COMPLETE snapshot was served in its place. The position was
1087
+ * accurate as of `staleAgeMs` ago; it is not a partial read (those are
1088
+ * `incomplete`) and it is never served for a lender that read successfully.
1089
+ */
1090
+ stale?: boolean;
1091
+ /** Age of the served snapshot in ms. Only set alongside `stale`. */
1092
+ staleAgeMs?: number;
1052
1093
  };
1053
1094
 
1054
- /** Reported per lender whose multicall slice contained failed reads. */
1095
+ /**
1096
+ * How a lender's slice reacts to a failed read.
1097
+ *
1098
+ * Note what this is NOT keyed on: "is the position cross-margin". EVERY position
1099
+ * with debt is corrupted by a lost read — an isolated Morpho market computes its
1100
+ * health from a collateral read and a debt read, so losing either fabricates the
1101
+ * same nonsense a lost Aave reserve does. The question here is narrower and
1102
+ * purely mechanical: **what is the smallest thing we can void?** A failed slot
1103
+ * carries no market label, so the only unit we can void is the lender key.
1104
+ *
1105
+ * - `strict` — void the whole slice on any lost read. Correct when the slice
1106
+ * resolves to ONE risk computation, which is true both for a single-market
1107
+ * lender and for a multi-market lender that is nevertheless cross-margin
1108
+ * (Exactly scores every market under one per-chain Auditor). Nothing smaller
1109
+ * can be voided, and publishing the remainder would publish a fiction.
1110
+ * - `lenient` — publish, flag `incomplete`, and let per-record invariant
1111
+ * validation catch the corrupted one. Correct ONLY when the slice fans out to
1112
+ * many INDEPENDENT isolated positions, where voiding the key would discard
1113
+ * hundreds of intact markets to hide one — a cure worse than the disease.
1114
+ *
1115
+ * So leniency requires BOTH properties: many independent positions AND no shared
1116
+ * risk computation across them.
1117
+ */
1118
+ type ReadFailurePolicy = 'strict' | 'lenient';
1119
+ declare const getReadFailurePolicy: (lender: string) => ReadFailurePolicy;
1120
+ /** Why a lender's slice did not convert cleanly. */
1121
+ type IncompleteReason =
1122
+ /** Every read in the slice failed. */
1123
+ 'all-reads-failed'
1124
+ /** Reads failed on a strict lender — the whole risk set was voided. */
1125
+ | 'partial-read-cross-margin'
1126
+ /** Reads failed on a lenient lender — surviving markets were published. */
1127
+ | 'partial-read'
1128
+ /** The converter threw. */
1129
+ | 'converter-error'
1130
+ /** The converted entry asserted something that cannot be true. */
1131
+ | 'invariant-violation';
1132
+ /** Reported per lender whose multicall slice did not convert cleanly. */
1055
1133
  interface IncompleteLenderRead {
1056
1134
  lender: string;
1057
1135
  /** Number of slots in the lender's slice that returned no data. */
1058
1136
  failedCalls: number;
1137
+ /**
1138
+ * Subset of `failedCalls` that could plausibly succeed on a re-read — i.e.
1139
+ * excluding calls known to have reverted. Zero means re-fetching this lender
1140
+ * is pointless: the markets in question always revert for this account.
1141
+ * Equals `failedCalls` when no `permanentFailures` set was supplied.
1142
+ */
1143
+ retryableFailedCalls: number;
1059
1144
  /** Size of the lender's slice. */
1060
1145
  totalCalls: number;
1061
- /** True when EVERY read failed and the lender was skipped entirely. */
1146
+ /** True when nothing was published for this lender. */
1062
1147
  dropped: boolean;
1148
+ /** What went wrong. */
1149
+ reason: IncompleteReason;
1150
+ /** Extra context for logs (converter message, violation details). */
1151
+ detail?: string;
1063
1152
  }
1064
1153
  interface ConvertLenderUserDataOptions {
1065
- /** Invoked once per lender with failed reads — for logging / surfacing. */
1154
+ /** Invoked once per lender that did not convert cleanly — for logging / surfacing. */
1066
1155
  onIncomplete?: (info: IncompleteLenderRead) => void;
1156
+ /**
1157
+ * Indices (into `rawResults`) of calls that failed deterministically, as
1158
+ * collected by `getLenderUserDataResult`. Used only to compute
1159
+ * `retryableFailedCalls`.
1160
+ */
1161
+ permanentFailures?: Set<number>;
1067
1162
  }
1068
1163
  /**
1069
1164
  * Converts the raw results into the desired format
1070
1165
  *
1071
1166
  * Slots that hold the multicall failure sentinel are NOT data: a failed read
1072
- * says nothing about the user's position. When every read for a lender failed
1073
- * the lender is skipped outright converting would emit an all-zero entry that
1074
- * is indistinguishable from "user has no position here", which is how a
1075
- * rate-limited RPC ends up rendering phantom $0 rows (and, when only some calls
1076
- * fail, understated balances). Partial failures still convert — the readable
1077
- * positions are real but are flagged `incomplete` and reported via
1078
- * `options.onIncomplete`.
1167
+ * says nothing about the user's position. Coercing one to zero is how a
1168
+ * rate-limited RPC ends up rendering phantom $0 rows and understated balances,
1169
+ * so failures are handled explicitly, in three gates:
1170
+ *
1171
+ * 1. **Failure policy** (see {@link ReadFailurePolicy}). Every read failing
1172
+ * drops the lender under either policy. Beyond that, a `strict`
1173
+ * (cross-margin) lender drops on ANY failure because its aggregates are only
1174
+ * meaningful over the complete set, while a `lenient` (multi-market) lender
1175
+ * publishes the markets that did read and is flagged `incomplete`.
1176
+ * 2. **Converter errors** are reported rather than swallowed — a throwing
1177
+ * converter used to leave a lender silently absent, indistinguishable from a
1178
+ * user with no position there.
1179
+ * 3. **Invariant validation** (see `validate.ts`) rejects sub-accounts that
1180
+ * cannot be true regardless of how the reads went — a `NaN` anywhere in the
1181
+ * aggregates, or (alongside failed reads) debt with no collateral behind it.
1182
+ *
1183
+ * Anything published after that is either complete or explicitly marked as not.
1079
1184
  *
1080
1185
  * @param chainId - The chain ID
1081
1186
  * @param queriesRaw - The queries to fetch data for
@@ -1088,6 +1193,53 @@ declare const convertLenderUserDataResult: (chainId: string, queriesRaw: LenderU
1088
1193
  [lender: string]: UserData;
1089
1194
  };
1090
1195
 
1196
+ /**
1197
+ * Why this exists SEPARATELY from the failure sentinels
1198
+ * -----------------------------------------------------
1199
+ * The sentinel path (`isFailedCall`) catches reads that announced themselves as
1200
+ * failures. This catches the ones that did not: a decodable-but-wrong response,
1201
+ * a market whose metadata went missing so its price resolved to `undefined`, a
1202
+ * converter that divided by a zero it should never have seen. Those produce the
1203
+ * SAME user-visible artefact as a dropped read — a debt with no collateral, a
1204
+ * `NaN` health factor — while every slot reports success.
1205
+ *
1206
+ * So this is the last gate before a position is published: it asserts what must
1207
+ * be true of any real lending position, independent of how the data was
1208
+ * obtained.
1209
+ */
1210
+ /** One failed assertion about a sub-account's published shape. */
1211
+ interface InvariantViolation {
1212
+ /** Sub-account this fired on (`accountId`). */
1213
+ accountId: string;
1214
+ /** Machine-readable check name. */
1215
+ code: 'non-finite' | 'debt-without-collateral' | 'invalid-mode';
1216
+ /** Human-readable detail for logs. */
1217
+ detail: string;
1218
+ /**
1219
+ * `true` when the violation is only conclusive because the read was also
1220
+ * known-incomplete (see {@link validateUserData}).
1221
+ */
1222
+ requiresFailedReads: boolean;
1223
+ }
1224
+ interface ValidationResult {
1225
+ /** Sub-accounts that passed. Empty means the whole entry must be dropped. */
1226
+ kept: UserDataForSubAccount[];
1227
+ /** Every violation found, including ones on kept sub-accounts. */
1228
+ violations: InvariantViolation[];
1229
+ /** Sub-account ids dropped as corrupt. */
1230
+ dropped: string[];
1231
+ }
1232
+ /**
1233
+ * Validates a converted entry and drops the sub-accounts that cannot be true.
1234
+ *
1235
+ * `hadFailedReads` gates the checks whose violation is ambiguous on its own:
1236
+ * with a known-incomplete read, `debt-without-collateral` is the signature of a
1237
+ * dropped collateral slot and the sub-account is corrupt; with a clean read it
1238
+ * is a genuine (if grim) position and is kept. Unconditional checks — anything
1239
+ * non-finite — fire either way, because no read produces those legitimately.
1240
+ */
1241
+ declare function validateUserData(userData: UserData, hadFailedReads: boolean): ValidationResult;
1242
+
1091
1243
  interface ExposureInfo {
1092
1244
  asset: GenericCurrency;
1093
1245
  collateralFactor: number;
@@ -1127,9 +1279,17 @@ declare function unflattenLenderData(pools: PoolWithMeta[]): LenderData;
1127
1279
  * @param logs - show multicall error logs, default is false
1128
1280
  * @param concurrency - number of distinct RPC endpoints to shard batches
1129
1281
  * across in parallel; <= 1 keeps the legacy single-endpoint path
1282
+ * @param permanentFailures - optional collector filled with the indices of
1283
+ * calls that failed DETERMINISTICALLY (revert / no code / unknown selector)
1284
+ * rather than because of the RPC. Pass it to
1285
+ * {@link convertLenderUserDataResult} so a caller can tell "this market
1286
+ * always reverts" from "this read was lost" and only re-fetch the latter.
1287
+ * @param onEndpointFailure - optional hook invoked for every RPC endpoint that
1288
+ * fails to serve a batch. Only the caller knows where to persist that (KV,
1289
+ * metrics), and without it every request rediscovers the same bad endpoint.
1130
1290
  * @returns The raw results from the multicall, "0x" for failures
1131
1291
  */
1132
- declare const getLenderUserDataResult: (chainId: string, queriesRaw: LenderUserQuery[], getEvmClient: GetEvmClientFunction, allowFailure?: boolean, batchSize?: number, retries?: number, logs?: boolean, concurrency?: number) => Promise<any[]>;
1292
+ declare const getLenderUserDataResult: (chainId: string, queriesRaw: LenderUserQuery[], getEvmClient: GetEvmClientFunction, allowFailure?: boolean, batchSize?: number, retries?: number, logs?: boolean, concurrency?: number, permanentFailures?: Set<number>, onEndpointFailure?: (info: EndpointFailure) => void) => Promise<any[]>;
1133
1293
  /**
1134
1294
  * Prepares the RPC calls for fetching user data without executing them
1135
1295
  * Uses multicall3 aggregate3 to batch all calls into a single RPC call
@@ -1484,6 +1644,21 @@ interface LenderDataEntry extends Omit<LenderSummary, 'subAccounts'> {
1484
1644
  account: string;
1485
1645
  lenderInfo?: LenderInfo;
1486
1646
  data: UserDataForSubAccount[];
1647
+ /**
1648
+ * Set when some of this lender's on-chain reads could not be completed. The
1649
+ * positions listed are real but the set is a LOWER BOUND — anything derived
1650
+ * from the whole picture (NAV, net APR, health factor) is unreliable and must
1651
+ * not be rendered as fact.
1652
+ */
1653
+ incomplete?: boolean;
1654
+ /**
1655
+ * Set when this entry was served from the last COMPLETE snapshot because the
1656
+ * live read failed. Internally consistent — unlike `incomplete` — but as of
1657
+ * `staleAgeMs` ago rather than now.
1658
+ */
1659
+ stale?: boolean;
1660
+ /** Age of the served snapshot in ms. Only set alongside `stale`. */
1661
+ staleAgeMs?: number;
1487
1662
  }
1488
1663
  /**
1489
1664
  * Input type for buildSummaries - user data result from convertLenderUserDataResult
@@ -8091,8 +8266,18 @@ declare function parseRawRpcBatchResponses(batches: RawRpcBatch[], batchResponse
8091
8266
  * Parses multicall3 aggregate3 responses
8092
8267
  * The response contains an array of {success, returnData} tuples
8093
8268
  * Each returnData needs to be decoded using the original call's ABI
8269
+ *
8270
+ * `permanentFailures`, when supplied, is filled with the indices of calls that
8271
+ * failed DETERMINISTICALLY. This path can tell them apart with certainty, which
8272
+ * the viem path can only infer: if the batch response itself came back, the
8273
+ * transport worked, so a `success: false` entry inside it is a revert — the
8274
+ * chain's answer, not a lost read. Only a batch-level error is a lost read.
8275
+ *
8276
+ * The distinction matters downstream: a cross-margin lender voids its whole set
8277
+ * on a lost read, and without this a single always-reverting market would void
8278
+ * a perfectly good position on every request.
8094
8279
  */
8095
- declare function parseMulticallRpcResponses(responses: RawRpcResponse[], batches: MulticallRpcBatch[], allowFailure?: boolean): any[];
8280
+ declare function parseMulticallRpcResponses(responses: RawRpcResponse[], batches: MulticallRpcBatch[], allowFailure?: boolean, permanentFailures?: Set<number>): any[];
8096
8281
 
8097
8282
  type TokenEntry = {
8098
8283
  chainId: string;
@@ -8185,4 +8370,1058 @@ interface FetchTokenBalancesOptions {
8185
8370
  */
8186
8371
  declare function fetchTokenBalances(chainId: string, account: string, tokens: string[], options?: FetchTokenBalancesOptions): Promise<TokenBalanceResult>;
8187
8372
 
8188
- export { type AaveMetadata, type AaveV2Public, type AaveV2UserReserveResponse, type AaveV3Public, type AaveV3UserReserveResponse, type AdditionalYields, ApiBookSource, type AprData, type BalanceData, type BaseLendingPosition, type BasicReserveResponse, type ChainDiagnostic, type ChainLinkResponse, type ChainQuery, type ChainSummary, type CompoundV2Metadata, type CompoundV3Public, type CompoundV3UserReserveResponse, type ConfigEntry, type CoreValidators, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, type Denomination, type DepthMap, EMPTY_BALANCE, type EModeAssets, type EModeData, type EModeResult, EXACTLY_LENDER_KEY, type EulerEarnVault, type EulerEarnVaults, type EulerV2Metadata, type ExactlyFixedPool, type ExactlyFixedPosition, type ExactlyMarketAccount, type ExactlyMarketsRaw, type ExactlyUserFixedPosition, type ExtraValidationCall, type FeedObservation, type FeedStat, type FeedStatsMap, type FeedTimestampMap, type FetchListaVaultsFromChainOptions, type FetchMorphoVaultsFromChainOptions, type FetchOraclePricesOptions, type FetchTokenBalancesOptions, type FlattenPriorityConfig, type FluidFToken, type FluidFTokens, type FrankencoinMarketRaw, type FrankencoinMarketsRaw, type FrankencoinPositionInfo, type FullLenderRewardsMap, GMX_API_HOSTS, GMX_READ_CONTRACTS, GMX_SUPPORTED_CHAINS, type GenericCurrency, type GenericTokenList, type GetVaultPublicDataAllOptions, type GmxExecutionFees, type GmxPendingDeposit, type GmxPendingWithdrawal, type GmxReadContracts, type GmxUserBalance, type GmxUserPositions, type GmxUserPositionsOptions, type GmxVault, type GmxVaultKind, type GmxVaults, type GmxVaultsFetchOptions, type GroupAccumulator, HYPERCORE_VAULT_REGISTRY, type HypercoreLockStatus, type HypercoreUserPositionsOptions, type HypercoreVault, type HypercoreVaultPosition, type HypercoreVaultRegistryEntry, type HypercoreVaults, type HypercoreVaultsFetchOptions, IDLE_MARKET_ID, INTERFACE_IDS, type InitMetadata, type InitPublic, type InitUserReserveResponse, type InterfaceKind, type InverseMarketRaw, type InverseMarketsRaw, type InversePositionInfo, LAGOON_API_URL, LAGOON_CHAIN_IDS, type LagoonApiVault, type LagoonSyncMode, type LagoonVault, type LagoonVaults, type LenderConfigData, type LenderConfigMap, type LenderCrossPoolMeta, type LenderData, type LenderDataEntry, type LenderInfo, type LenderInfoMap, type LenderPublicBase, type LenderRewardsMap, type LenderSummary, type LenderToLenderCrossPoolMeta, type LenderTotalAmounts, type LenderUserQuery, type LenderUserResponse, type LenderYieldComplete, type LenderYields$1 as LenderYields, LendingMode, type LiquityBranchRaw, type LiquityDiscoveredTrove, type LiquityDiscovery, type LiquityMarketsRaw, type LiquitySpInfo, type LiquityTroveInfo, type ListaMarketOverrides, type LlamaLendMarketRaw, type LlamaLendMarketsRaw, type LlamaLendPositionInfo, type LoopPostTradeMetrics, type LstDelegation, type LstDelegationKind, type LstValidator, type LstWithdrawalFetchOptions, type LstWithdrawalRegistryEntry, type LstWithdrawalRequest, type LstWithdrawalRequestsByLst, type LstWithdrawalStatus, MORPHO_LENS, MaxParamThresholds, type MergedUserData, type MidnightBook, type MidnightBookLevel, type MidnightBookSource, type ModeBase, type MorphoMarketOverrides, type MorphoSubgraphProxyConfig, type MorphoUserMarketBalance, type MorphoUserReserveResponse, type MorphoVault, type MorphoVaults, type MulticallRpcBatch, type NumberMap, type OracleDiagnostics, type OraclePriceEntry, type OraclePricesResult, type OutlierGuardConfig, type ParsedBalanceData, type ParsedResponse, type ParsedUserBalance, type PermissionParams, type PoolData, type PoolWithMeta, type PortfolioSummary, type PortfolioTotals, type PostTradeMetrics, type PreparedCall, type PreparedMergedMulticallParams, type PreparedMergedRpcCalls, type PreparedTokenBalanceRpcCalls, type PreparedUserDataRpcCalls, type PriceDerivation, type PriceSelection, type ProtocolParams, type ProviderOptions, type RawRpcBatch, type RawRpcCall, type RawRpcResponse, type ResupplyMarketsRaw, type ResupplyPairIdentity, type ResupplyPairRaw, type ResupplyPositionInfo, type ResupplyWrappedMarket, type RiverMarketRaw, type RiverMarketsRaw, type RiverPositionInfo, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, type SelectPricesOptions, type SiloVault, type SiloVaults, type StCeloValidatorGroup, type StaleFeedEntry, type StructuredOraclePrices, type SubAccountSummary, type SumerPositionInput, type SummaryAprData, type SummaryBalanceData, TELLER_CALLS_PER_BID, TERMMAX_CALLS_PER_ACCOUNT, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, TERMMAX_PARTIAL_CLOSE_FACTOR, TERMMAX_PARTIAL_LIQUIDATION_THRESHOLD_USD, type TellerDiscoveredBid, type TellerDiscovery, type TellerMarketsRaw, type TellerPoolRaw, type TermAuctionOrder, type TermAuctionOrders, type TermBookSource, type TermBookTop, type TermListing, type TermMarketRaw, TermMaxApiSource, type TermMaxBookTop, type TermMaxCurveSegment, type TermMaxDataSource, type TermMaxDiscovery, type TermMaxFeeConfig, type TermMaxMarketConfig, type TermMaxMarketRaw, type TermMaxOrderState, TermSubgraphSource, type TokenApprovalMeta, type TokenApprovalParams, type TokenBalanceEntry, type TokenBalanceQuery, type TokenBalanceResult, type TokenEntry, type TokenList, type TokenListInput, type TrackerDiagnostic, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, type USDPriceMap, type UpshiftApiAsset, type UpshiftApiVault, type UpshiftVault, type UpshiftVaults, type UsddMarketRaw, type UsddMarketsRaw, type UsddPositionInfo, type UserApr, type UserConfig, type UserData, type UserDataResult, type UserLendingPosition, VAULT_SHARE_PRICE_PROBE, VOLATILE_VAULT_OVERRIDES, type VaultAprResult, type VaultClassification, type VaultClassificationFields, type VaultLookupEntry, type VaultMarketExposure, type VaultProvider, type VaultPublicDataAll, type VaultPublicDataResult, type VaultYieldSeries, type VaultYieldSnapshot, type YDaemonVault, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, type YearnVault, type YearnVaultKind, type YearnVaults, type YieldProfile, __resetResupplyUserCaches, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyPositionDelta, attachPricesToFlashLiquidity, buildFluidFTokensCall, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildVaultLookup, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, collectFeedObservations, computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeVaultApr, computeWithdrawDelta, computeZapTradeDeltas, consensusReference, convertExactlyMarketsToResponse, convertFrankencoinMarketsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertLlamaLendMarketsToResponse, convertResupplyMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, detectInterfaceKinds, encodeBalanceFetcherCalldata, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feedKeyOf, feedStatKey, fetchDolomiteAccountNumbers, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchFrankencoinMarkets, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchLlamaLendMarkets, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendlePrices, fetchResupplyMarkets, fetchRiverMarkets, fetchSiloVaults, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, frankencoinKeyParts, frankencoinLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedLiquityTroves, getCachedTellerBids, getCachedTermMaxDiscovery, getCachedTermMaxMarket, getCachedTermMaxMarkets, getCoreValidators, getFluidFTokensConverter, getGmxApiHost, getGmxReadContracts, getGmxUserPositions, getHealthFactor, getHypercoreUserPositions, getHypercoreVaultRegistry, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getLstDelegation, getLstValidators, getLstWithdrawalRegistry, getLstWithdrawalRequests, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getVaultPublicDataAll, getVaultWithdrawalRequests, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasUpshiftVaults, hasYearnVaults, inverseKeyParts, inverseLenderKey, isStablecoinSymbol, isYearnV3, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTermMaxLtv, parseTokenBalanceResult, positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveDerivation, resolveStCeloDepositGroup, resupplyKeyParts, resupplyLenderKey, riverKeyParts, riverLenderKey, selectAssetGroupPrices, stampVaultClassification, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termLenderKey, termMaxApiBase, borrowNif as termMaxBorrowNif, curveApr as termMaxCurveApr, curveAprNumber as termMaxCurveAprNumber, daysToMaturity as termMaxDaysToMaturity, lendNif as termMaxLendNif, mintGtFeeRatio as termMaxMintGtFeeRatio, ratioToNumber as termMaxRatioToNumber, ratioToPercent as termMaxRatioToPercent, tickToAprNumber, tickToPrice, unflattenLenderData, updateFeedStats, usddIlkBytes32, usddKeyParts, usddLenderKey };
8373
+ /**
8374
+ * Term sheets — a structured, per-`marketUid` description of every lend and
8375
+ * borrow offer we serve.
8376
+ *
8377
+ * One shape for pool lenders, fixed-term lenders, CDPs and vaults, so an
8378
+ * integrator reads ONE object instead of ~15 protocol-specific fields plus a
8379
+ * per-lender mental model. See [TERM_SHEET_PLAN.md](../../../../TERM_SHEET_PLAN.md)
8380
+ * for the design rationale and the per-lender coverage matrix.
8381
+ *
8382
+ * ## Conventions that hold everywhere in this file
8383
+ *
8384
+ * - **Rates are nominal APR in PERCENT** (`3.85` = 3.85 %/yr), never a
8385
+ * fraction and never an APY. This is the package-wide convention.
8386
+ * - **Factors are fractions** (`0.85` = 85 % LTV) — matching `LenderConfigData`.
8387
+ * - **Durations are SECONDS**, timestamps are **unix seconds**.
8388
+ * - **Raw amounts are decimal strings** in base units; human amounts are
8389
+ * `number`.
8390
+ * - Every string union is deliberately OPEN (`| (string & {})`) so a new
8391
+ * lender can introduce a member without breaking a consumer's exhaustive
8392
+ * switch. Consumers MUST have a `default` branch and fall back to
8393
+ * `info.headline`.
8394
+ */
8395
+ /** Nominal APR in percent (`3.85` = 3.85 %/yr). Never a fraction, never APY. */
8396
+ type AprPercent = number;
8397
+ /**
8398
+ * Open-enum helper. `Open<'a' | 'b'>` keeps autocomplete for the known members
8399
+ * while still accepting any string, so adding a member later is an ADDITIVE
8400
+ * change rather than a breaking one.
8401
+ */
8402
+ type Open<T extends string> = T | (string & {});
8403
+ /** Compact token reference — enough to render without a second lookup. */
8404
+ interface TermAssetRef {
8405
+ chainId: string;
8406
+ /** Lowercased contract address. */
8407
+ address: string;
8408
+ symbol?: string;
8409
+ name?: string;
8410
+ decimals?: number;
8411
+ assetGroup?: string;
8412
+ logoURI?: string;
8413
+ }
8414
+ /**
8415
+ * Machine tags for filtering/faceting. DERIVED from the structured fields in
8416
+ * `tags.ts` — never hand-written per lender, so they cannot drift from the
8417
+ * numbers they summarize.
8418
+ */
8419
+ type TermTag = Open<'fixed-rate' | 'variable-rate' | 'user-set-rate' | 'zero-interest' | 'prepaid-interest' | 'nav-accrual' | 'has-maturity' | 'perpetual' | 'rolling-duration' | 'static-debt' | 'accruing-debt' | 'time-liquidation' | 'price-liquidation' | 'redeemable' | 'no-liquidation' | 'full-collateral-seizure' | 'early-exit-free' | 'early-exit-penalty' | 'early-exit-discount' | 'exit-instant' | 'exit-capped' | 'exit-cooldown' | 'exit-queued' | 'exit-market-sale' | 'exit-may-be-impossible' | 'permissioned' | 'capped' | 'cap-full' | 'first-loss' | 'socialized-loss' | 'physical-delivery' | 'undercollateralized' | 'nav-attested' | 'immutable' | 'no-timelock' | 'eoa-controlled' | 'points-rewards' | 'oracle-flagged' | 'no-oracle'>;
8420
+ /** Human-facing copy for one side of a term sheet. */
8421
+ interface TermInfo {
8422
+ /**
8423
+ * ≤ ~100 chars, templated from live numbers, ready to render.
8424
+ * `"Fixed 4.12 % until 3 Sep 2026 · repay any time at face value"`.
8425
+ *
8426
+ * ALWAYS populated — it is the graceful-degradation path for a consumer
8427
+ * that does not recognise a newer enum member.
8428
+ */
8429
+ headline: string;
8430
+ /** 1–3 sentences. Invariant prose lives on the profile; this interpolates
8431
+ * the market's own values. */
8432
+ description: string;
8433
+ /** Ready-to-display consequences, most important first. */
8434
+ implications?: string[];
8435
+ tags: TermTag[];
8436
+ }
8437
+ type RateKind = Open<
8438
+ /** Utilization IRM (Aave, Compound, Morpho, Silo, Euler, Fluid…). */
8439
+ 'variable-curve'
8440
+ /** Governance-set with no curve (USDD stability fee, Spark `vsr`). */
8441
+ | 'variable-managed'
8442
+ /** Borrower picks the rate (Liquity family). */
8443
+ | 'user-set'
8444
+ /** Locked for a maturity (Exactly, Midnight, Term, TermMax, Teller, Lista). */
8445
+ | 'fixed-term'
8446
+ /** Locked, no maturity. Reserved — nothing uses it today. */
8447
+ | 'fixed-open'
8448
+ /** No ongoing rate at all (River); cost is a one-off fee. */
8449
+ | 'zero-interest'
8450
+ /** Interest prepaid in a separate token (Inverse DBR). */
8451
+ | 'prepaid'
8452
+ /** Share price tracks an attested NAV (Re, Apyx, USPC). */
8453
+ | 'nav-accrual'
8454
+ /** Pure collateral leg — no yield. */
8455
+ | 'none'>;
8456
+ /** One reward program. Identity matters: points are not a bankable APR. */
8457
+ interface RewardTerm {
8458
+ /** Absent for points programs — that absence IS the signal. */
8459
+ asset?: TermAssetRef;
8460
+ kind: Open<'token' | 'points' | 'unknown'>;
8461
+ apr: AprPercent;
8462
+ side: 'supply' | 'borrow';
8463
+ /** How it is realized — decides whether the APR is actually bankable. */
8464
+ claim: Open<'accrual' | 'merkl' | 'manual' | 'none'>;
8465
+ /** Program end, where known. An APR with two weeks left is not an APR. */
8466
+ endsAt?: number;
8467
+ /**
8468
+ * `true` ⇒ not priceable (points). MUST be shown separately and is
8469
+ * deliberately EXCLUDED from `RateTerms.aprTotal`.
8470
+ */
8471
+ indicative?: boolean;
8472
+ }
8473
+ /** One entry in a fixed-term rate menu. Mirrors `MarketTermEntry`. */
8474
+ interface RateMenuEntry {
8475
+ /** LENDER-SPECIFIC: Exactly/TermMax = unix maturity, Teller = duration
8476
+ * seconds, Lista = broker product id, Midnight/Term = `0`. */
8477
+ termId: number;
8478
+ durationSecs: number;
8479
+ durationDays: number;
8480
+ /** Borrow APR at this term. */
8481
+ apr: AprPercent;
8482
+ /** Lend APR at this term, where the lender quotes both sides. */
8483
+ depositApr?: AprPercent;
8484
+ /** Borrowable liquidity at this term, human units. */
8485
+ available?: number;
8486
+ }
8487
+ interface RateTerms {
8488
+ kind: RateKind;
8489
+ /** Base rate only — no rewards, no intrinsic yield. */
8490
+ apr: AprPercent;
8491
+ components: {
8492
+ base: AprPercent;
8493
+ /** Priceable rewards only. */
8494
+ rewards?: AprPercent;
8495
+ /** Underlying/LST yield the asset earns by itself. */
8496
+ intrinsic?: AprPercent;
8497
+ };
8498
+ /** `base + priceable rewards + intrinsic` — the headline number. */
8499
+ aprTotal: AprPercent;
8500
+ /** Carried explicitly even though it has one value today: a silent
8501
+ * APR→APY change would be the classic undetectable break. */
8502
+ basis: 'apr-nominal';
8503
+ compounding: Open<'per-second' | 'per-block' | 'none' | 'unknown'>;
8504
+ source: Open<'utilization-curve' | 'orderbook' | 'auction' | 'governance' | 'borrower' | 'oracle' | 'api' | 'derived'>;
8505
+ /** Is the rate locked for the life of the position? */
8506
+ isLocked: boolean;
8507
+ /** Protocol-enforced bounds (Liquity min/max, Morpho rateCap/rateFloor). */
8508
+ minApr?: AprPercent;
8509
+ maxApr?: AprPercent;
8510
+ /** Per-program reward detail — token identity, claim path, end date. */
8511
+ rewards?: RewardTerm[];
8512
+ /** Rate menu when the market offers several terms at once. */
8513
+ menu?: RateMenuEntry[];
8514
+ /** Size the quote is valid for, when the rate is depth-dependent. */
8515
+ quote?: {
8516
+ assets: number;
8517
+ basis: Open<'marginal' | 'average'>;
8518
+ };
8519
+ lastChangedAt?: number;
8520
+ }
8521
+ interface MaturityTerms {
8522
+ kind: Open<'perpetual' | 'fixed-date' | 'rolling-duration'>;
8523
+ /** unix seconds; `kind: 'fixed-date'`. */
8524
+ maturity?: number;
8525
+ /** ISO-8601 mirror so consumers need not re-format. */
8526
+ maturityIso?: string;
8527
+ /** Snapshot — derive live from `maturity` for a countdown. */
8528
+ secondsToMaturity?: number;
8529
+ /** `kind: 'rolling-duration'` (Teller, Lista broker). */
8530
+ minDurationSecs?: number;
8531
+ maxDurationSecs?: number;
8532
+ /**
8533
+ * What happens at/after maturity if NOBODY acts. The field that most
8534
+ * surprises users — outcomes range from "interest simply stops" to
8535
+ * "liquidated within five minutes, losing all collateral".
8536
+ */
8537
+ atMaturity?: Open<'stops-earning' | 'penalty-accrues' | 'liquidatable' | 'default-seizure' | 'physical-delivery' | 'refinanced' | 'auto-roll' | 'none'>;
8538
+ /** Grace window before `atMaturity` bites (Teller ~300 s, TermMax 7200 s). */
8539
+ graceSecs?: number;
8540
+ }
8541
+ type FeeWhen = Open<'entry' | 'ongoing' | 'exit' | 'late' | 'liquidation' | 'performance'>;
8542
+ /**
8543
+ * One charge, in a shape general enough that a NEW fee is data rather than a
8544
+ * schema change. Replaces the current scatter: `originationFee`,
8545
+ * `withdrawFeeBps`, `rates.fee`, `fixedTerm.fees.*`, `river.mintFeeRate`,
8546
+ * `liquity.gasCompensation`.
8547
+ */
8548
+ interface FeeTerm {
8549
+ /** Stable slug — the join key for UI copy and filtering. */
8550
+ id: Open<'origination' | 'late-penalty' | 'early-repay-penalty' | 'early-repay-discount' | 'continuous' | 'settlement' | 'instant-exit' | 'performance' | 'reserve-factor' | 'gas-compensation' | 'redemption' | 'claim' | 'liquidation-bonus'>;
8551
+ /** Human label — lets an unknown `id` still render correctly. */
8552
+ label: string;
8553
+ when: FeeWhen;
8554
+ unit: Open<'apr-percent' | 'percent' | 'bps' | 'absolute'>;
8555
+ basis: Open<'principal' | 'face-value' | 'yield' | 'collateral' | 'shares' | 'debt-repaid'>;
8556
+ /**
8557
+ * A NEGATIVE value is legal and means a REBATE (Exactly's early-repay
8558
+ * discount). Sign is load-bearing — never take an absolute value.
8559
+ */
8560
+ value: number;
8561
+ payee?: Open<'protocol' | 'lenders' | 'liquidator' | 'curator' | 'gas-refund'>;
8562
+ /** Governance-mutable ⇒ this is a snapshot; re-verify before quoting. */
8563
+ mutable?: boolean;
8564
+ /** Only resolvable at action time (Exactly discount, TermMax curve price). */
8565
+ indicative?: boolean;
8566
+ /** Decaying/scheduled fees (Apyx: 3.40 % → 0 over 20 days). */
8567
+ schedule?: {
8568
+ afterSecs: number;
8569
+ value: number;
8570
+ }[];
8571
+ description?: string;
8572
+ }
8573
+ /** Superset of `SavingsWithdrawalMode` + `LstWithdrawalMode`, plus the two
8574
+ * lending-side exits neither covers. */
8575
+ type SupplyExitMode = Open<'instant' | 'instant-capped' | 'instant-or-queued' | 'fee-or-queued' | 'fixed-cooldown' | 'queued' | 'request-based'
8576
+ /** Sell the instrument on a book (Term, TermMax, Midnight). */
8577
+ | 'market-sale'
8578
+ /** No early exit at all. */
8579
+ | 'at-maturity' | 'off-chain' | 'dex-only'>;
8580
+ interface SupplyExitTerms {
8581
+ mode: SupplyExitMode;
8582
+ /** Coarse alias — identical semantics to `VaultClassificationFields.redemptionType`. */
8583
+ settlement: Open<'sync' | 'async'>;
8584
+ cooldownSecs?: number;
8585
+ /** Claim-window constraints (Apyx: blocked 3 d, free at 20 d). */
8586
+ claimWindow?: {
8587
+ earliestSecs?: number;
8588
+ freeAfterSecs?: number;
8589
+ };
8590
+ /** What can actually leave right now. */
8591
+ liquidity?: {
8592
+ assets: number;
8593
+ assetsUsd?: number;
8594
+ ratio?: number;
8595
+ };
8596
+ partialAllowed: boolean;
8597
+ /**
8598
+ * Does exiting early cost an UNKNOWN amount?
8599
+ * `none` par · `haircut-formula` deterministic discount ·
8600
+ * `market-price` you sell into a book · `may-be-impossible` the book can be
8601
+ * empty.
8602
+ */
8603
+ priceRisk: Open<'none' | 'haircut-formula' | 'market-price' | 'may-be-impossible'>;
8604
+ cancellable?: boolean;
8605
+ /** The `when: 'exit' | 'performance'` subset of the side's fees. */
8606
+ fees: FeeTerm[];
8607
+ }
8608
+ interface BorrowExitTerms {
8609
+ /** Three signs exist across our lenders: `discount` is a REBATE (Exactly). */
8610
+ earlyRepay: Open<'free' | 'discount' | 'penalty' | 'market-price' | 'not-allowed'>;
8611
+ atMaturityCost: Open<'face' | 'accrued'>;
8612
+ lateBehaviour: Open<'penalty-accrues' | 'liquidatable' | 'default-seizure' | 'refinanced' | 'none'>;
8613
+ partialAllowed: boolean;
8614
+ /** Dust floor — Liquity `minDebt`, Morpho/Lista `minLoan`. Raw base units. */
8615
+ minDebt?: string;
8616
+ /** Over-repay REVERTS (Midnight `uint128` underflow) — a real footgun. */
8617
+ overRepayReverts?: boolean;
8618
+ fees: FeeTerm[];
8619
+ }
8620
+ interface LiquidationTerms {
8621
+ trigger: Open<'price' | 'time' | 'price-and-time' | 'redemption' | 'none'>;
8622
+ /** Max LTV at open. */
8623
+ ltv?: number;
8624
+ /** Threshold at which liquidation becomes possible. */
8625
+ liquidationLtv?: number;
8626
+ /** Fraction of repaid debt paid to the liquidator on top of par. */
8627
+ penalty: number;
8628
+ closeFactor: number;
8629
+ targetHealthFactor?: number;
8630
+ /**
8631
+ * `full-collateral` is the Teller case: the liquidator takes the ENTIRE
8632
+ * escrow, not a proportional slice — ~2× the debt at 50 % LTV.
8633
+ */
8634
+ seizure: Open<'proportional' | 'full-collateral'>;
8635
+ /** Liquity/River: collateral redeemable at par while perfectly healthy. */
8636
+ redeemable?: boolean;
8637
+ gracePeriodSecs?: number;
8638
+ }
8639
+ interface CounterpartyTerms {
8640
+ kind: Open<'pool' | 'orderbook' | 'auction' | 'broker' | 'cdp' | 'p2p' | 'vault-strategy' | 'off-chain-credit'>;
8641
+ address?: string;
8642
+ /** The trust question, one field. */
8643
+ solvency: Open<'overcollateralized' | 'tranched-senior' | 'tranched-junior' | 'undercollateralized' | 'nav-attested'>;
8644
+ socializedLoss?: boolean;
8645
+ curator?: string;
8646
+ }
8647
+ /** Origination window for auction-gated markets (Term Finance). */
8648
+ interface AuctionWindow {
8649
+ status: Open<'upcoming' | 'open' | 'revealing' | 'closed'>;
8650
+ canBorrow: boolean;
8651
+ canLend: boolean;
8652
+ secondsUntilClose?: number;
8653
+ id?: string;
8654
+ startTime?: number;
8655
+ revealTime?: number;
8656
+ endTime?: number;
8657
+ minBorrowAmount?: string;
8658
+ minLendAmount?: string;
8659
+ }
8660
+ /** What must be granted BEFORE an action can even be built. */
8661
+ type PermissionKind = Open<'token-approval' | 'lender-delegation' | 'manager-authorization' | 'eip712-permit' | 'nft-approval' | 'operator-set'
8662
+ /** Contract callers must be governance-approved (Inverse, Fraxlend). */
8663
+ | 'caller-allowlist'>;
8664
+ interface AvailabilityTerms {
8665
+ /** Gate CTAs on THIS and nothing else — it already folds in caps, freezes,
8666
+ * auction windows and gating. */
8667
+ canOpen: boolean;
8668
+ canClose: boolean;
8669
+ /** Machine-readable reason when `canOpen` is false. */
8670
+ blockedBy?: Open<'frozen' | 'paused' | 'cap-full' | 'auction-closed' | 'no-liquidity' | 'not-whitelisted' | 'shutdown' | 'disabled'>;
8671
+ gating: Open<'permissionless' | 'whitelist' | 'attestation' | 'kyc' | 'allowlist-contract'>;
8672
+ /** Absent ⇒ no window applies. NOT the same as `closed`. */
8673
+ window?: AuctionWindow;
8674
+ /** Raw base units. */
8675
+ minSize?: string;
8676
+ cap?: string;
8677
+ /** 0..1 — how full the cap is. */
8678
+ capUtilization?: number;
8679
+ requires?: PermissionKind[];
8680
+ }
8681
+ interface PositionConstraints {
8682
+ /** Aave isolation mode: capped debt, no collateral mixing. */
8683
+ isolation?: {
8684
+ enabled: boolean;
8685
+ debtCeiling?: string;
8686
+ ceilingUtilization?: number;
8687
+ };
8688
+ /** Borrowing this asset forbids borrowing any other in the same account. */
8689
+ siloedBorrowing?: boolean;
8690
+ crossMargin: boolean;
8691
+ /**
8692
+ * How a position is ADDRESSED. `loanId` already means five different things
8693
+ * across our lenders and `termId` six — making the model explicit is
8694
+ * cheaper than making every integrator rediscover it.
8695
+ */
8696
+ positionModel: Open<'account' | 'sub-account' | 'nft' | 'cdp-id' | 'loan-id' | 'escrow'>;
8697
+ /** One line saying what the id in `loanId`/`posId` actually IS here. */
8698
+ positionIdMeaning?: string;
8699
+ maxPositions?: number;
8700
+ /**
8701
+ * What this fetch actually SAW, as opposed to what the lender family
8702
+ * implies. Kept separate from `crossMargin` / `positionModel` on purpose:
8703
+ * those are family-level truths from the registry, these are per-fetch
8704
+ * observations, and collapsing the two would let a thin chain (a lender
8705
+ * listing one asset today) masquerade as a structural property.
8706
+ *
8707
+ * Useful precisely where they DISAGREE — e.g. Fluid is registered isolated
8708
+ * because its T1 vaults dominate, but its T2–T4 "smart" vaults genuinely
8709
+ * pool two collaterals; a `collateralAssetCount > 1` on a Fluid row is the
8710
+ * signal that this particular vault is one of them.
8711
+ */
8712
+ observed?: {
8713
+ /** Distinct collateral assets this market actually accepts, this fetch. */
8714
+ collateralAssetCount: number;
8715
+ /** Markets seen under this lender key on this chain, this fetch. */
8716
+ marketCount: number;
8717
+ /** Does the lender key fan out to many markets (registry answer)? */
8718
+ multiMarketKey: boolean;
8719
+ };
8720
+ }
8721
+ type AdminKind = Open<'EOA' | 'SAFE' | 'TIMELOCK' | 'GOVERNOR' | 'GOVERNANCE' | 'CUSTOM' | 'UNKNOWN'>;
8722
+ type GovernancePower = Open<'pause-deposits' | 'pause-withdrawals' | 'pause-borrows' | 'freeze-market' | 'change-ltv' | 'change-rate' | 'change-fees' | 'set-caps' | 'add-collateral' | 'swap-oracle' | 'upgrade-implementation' | 'blacklist' | 'seize-funds' | 'reprice-pending-redemptions'>;
8723
+ interface GovernanceTerms {
8724
+ mutability: Open<'immutable' | 'governed' | 'unknown'>;
8725
+ /** The governance root, after hopping proxy admins / timelock admins. */
8726
+ controller?: string;
8727
+ controllerKind?: AdminKind;
8728
+ safe?: {
8729
+ threshold: number;
8730
+ owners: number;
8731
+ };
8732
+ /**
8733
+ * Enforced delay in SECONDS between a parameter change being queued and it
8734
+ * taking effect — the holder's NOTICE PERIOD. `0`, or any `controllerKind`
8735
+ * that is not `TIMELOCK`, means a parameter can change in the very next
8736
+ * block with no warning.
8737
+ *
8738
+ * **This is NOT a withdrawal lock.** `SupplyExitTerms.cooldownSecs` is how
8739
+ * long YOUR money is stuck; this is how long you have to react to someone
8740
+ * else changing the deal. Never merge or sum the two.
8741
+ */
8742
+ timelockSecs?: number;
8743
+ timelockSource?: Open<'on-chain' | 'screened' | 'metadata'>;
8744
+ /**
8745
+ * The controller IS a timelock but its delay could not be read. Distinct
8746
+ * from `timelockSecs: undefined` on a non-timelock root, which genuinely
8747
+ * means "no notice period" — conflating the two would raise a false alarm
8748
+ * on the safest governance shape.
8749
+ */
8750
+ timelockUnknown?: boolean;
8751
+ tier?: Open<'low' | 'medium' | 'high' | 'unknown'>;
8752
+ score?: number;
8753
+ powers?: GovernancePower[];
8754
+ roles?: {
8755
+ owner?: string;
8756
+ curator?: string;
8757
+ guardian?: string;
8758
+ feeRecipient?: string;
8759
+ };
8760
+ /** Governance screens refresh far slower than rates — own timestamp. */
8761
+ asOfScreen?: number;
8762
+ }
8763
+ type OracleBand = Open<'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL'>;
8764
+ interface OracleTerms {
8765
+ /**
8766
+ * `none` is MEANINGFUL, not missing data: Teller liquidates on TIME and has
8767
+ * no oracle and no health factor anywhere in its trigger.
8768
+ */
8769
+ kind: Open<'price-feed' | 'nav-attested' | 'none'>;
8770
+ /**
8771
+ * THE oracle for this `marketUid` — SINGULAR, lowercased. Verified across
8772
+ * the full oracle classification: 8,993 marketUids, 0 with more than one
8773
+ * address. Singularity holds because `marketUid` granularity is already
8774
+ * per-asset; the array in the legacy `oracleInfo.feeds[]` is an artifact of
8775
+ * hanging off the lender/params level instead.
8776
+ *
8777
+ * For a composite/cross adapter this is the ADAPTER — the address whose
8778
+ * failure or replacement moves this market's price.
8779
+ */
8780
+ address?: string;
8781
+ /** Underlying feeds when the adapter composes several and the classifier
8782
+ * decomposed them. `address` stays the single source of truth. */
8783
+ components?: string[];
8784
+ provider?: string;
8785
+ /** Decoded reported pair, e.g. `"ETH / USD"`. */
8786
+ priceDescription?: string;
8787
+ /** What it SHOULD report, e.g. `"WETH / USD"`. */
8788
+ intendedPair?: string;
8789
+ correctAsset?: boolean | null;
8790
+ correctNumeraire?: boolean | null;
8791
+ fixedRate?: boolean;
8792
+ score?: number;
8793
+ band?: OracleBand;
8794
+ flags?: string[];
8795
+ /** Can the oracle be swapped/upgraded, and by whom. On an otherwise
8796
+ * IMMUTABLE market this is the ONLY mutable trust vector. */
8797
+ mutability?: {
8798
+ mutable: boolean;
8799
+ kind: Open<'IMMUTABLE' | 'PROXY' | 'AUTHORITY' | 'UNKNOWN'>;
8800
+ controller?: string;
8801
+ controllerKind?: AdminKind;
8802
+ timelockSecs?: number;
8803
+ };
8804
+ heartbeatSecs?: number;
8805
+ lastUpdateAt?: number;
8806
+ }
8807
+ interface AssetQuality {
8808
+ /** 1 (best) … 5 (worst). */
8809
+ riskScore?: number;
8810
+ source?: Open<'whitelist' | 'default' | 'curated'>;
8811
+ /** On-chain USD liquidity available to absorb a liquidation — the number
8812
+ * that decides whether the LLTV is actually enforceable. */
8813
+ liquidityUsd?: number;
8814
+ /** The TOKEN CONTRACT's own governance, distinct from the market's. An
8815
+ * upgradeable, pausable collateral is a supplier risk even on an
8816
+ * immutable market. */
8817
+ governanceScore?: number;
8818
+ governanceLevel?: Open<'green' | 'amber' | 'red'>;
8819
+ upgradeable?: boolean;
8820
+ canPause?: boolean;
8821
+ adminKind?: AdminKind;
8822
+ }
8823
+ interface ExposureEntry {
8824
+ asset: TermAssetRef;
8825
+ /** That asset's OWN row in this lender — join key to its full term sheet. */
8826
+ marketUid?: string;
8827
+ via: Open<'collateral' | 'vault-allocation' | 'strategy' | 'idle'>;
8828
+ assets?: number;
8829
+ assetsUsd?: number;
8830
+ /** 0..100. ABSENT when `weightBasis === 'unweighted'`. */
8831
+ weightPct?: number;
8832
+ ltv?: number;
8833
+ liquidationLtv?: number;
8834
+ liquidationPenalty?: number;
8835
+ /** The collateral's OWN oracle. Your deposit's safety depends on the oracle
8836
+ * pricing SOMEONE ELSE'S collateral. */
8837
+ oracle?: OracleTerms;
8838
+ quality?: AssetQuality;
8839
+ }
8840
+ interface ExposureTerms {
8841
+ count: number;
8842
+ /**
8843
+ * How `weightPct` was obtained, and therefore how much to trust it.
8844
+ * `unweighted` = POOLED lenders: Aave/Compound do not record which
8845
+ * collateral backs which borrow on-chain, so the list is the ACCEPTED SET,
8846
+ * not a measured split. Do not render a pie chart from it.
8847
+ */
8848
+ weightBasis: Open<'debt' | 'allocation' | 'unweighted'>;
8849
+ worstRiskScore?: number;
8850
+ worstOracleBand?: OracleBand;
8851
+ /** Largest single exposure's `weightPct` — the concentration signal. Only
8852
+ * meaningful when `weightBasis !== 'unweighted'`. */
8853
+ topWeightPct?: number;
8854
+ items: ExposureEntry[];
8855
+ }
8856
+ interface UtilizationTerms {
8857
+ /** borrowed / supplied, 0..1 — the IRM input for this market. */
8858
+ utilization: number;
8859
+ /**
8860
+ * The basis the ratio is computed over. NOT always this row: rates for
8861
+ * shared-liquidity protocols are set on a larger pool, and a simulation
8862
+ * must shift THAT, not the row totals.
8863
+ */
8864
+ basis: Open<'market' | 'hub' | 'liquidity-layer' | 'pool'>;
8865
+ irmTotalDeposits?: number;
8866
+ irmTotalDebt?: number;
8867
+ /** Where the curve steepens — headroom before the rate jumps. */
8868
+ targetUtilization?: number;
8869
+ kinkUtilization?: number;
8870
+ /** 0..1. `1` = cap full and the side is closed. */
8871
+ supplyCapUtilization?: number;
8872
+ borrowCapUtilization?: number;
8873
+ /** Fluid: share of collateral locked below the withdrawal limit. */
8874
+ lockupRatio?: number;
8875
+ }
8876
+ /**
8877
+ * A non-default risk category, expressed as a DELTA against the resolved
8878
+ * default. `config` is a MAP keyed by category (Aave e-modes, Dolomite
8879
+ * categories, Euler configs, Silo) — a single flat LTV silently reports the
8880
+ * default and hides the rest, which on an Aave ETH-correlated e-mode is the
8881
+ * difference between 80 % and 93 %.
8882
+ */
8883
+ interface ModeVariant {
8884
+ /** The `config` map key. `'0'` is the default on every lender. */
8885
+ modeId: string;
8886
+ label?: string;
8887
+ isDefault: boolean;
8888
+ entry?: Open<'automatic' | 'user-selected' | 'per-position'>;
8889
+ liquidation?: Partial<LiquidationTerms>;
8890
+ /**
8891
+ * Mode-scoped and usually RESTRICTED: an e-mode typically narrows the
8892
+ * accepted collateral to a correlated basket. Omitting it would make the
8893
+ * headline LTV look obtainable against collateral the mode forbids.
8894
+ */
8895
+ acceptedCollateral?: ExposureTerms;
8896
+ rate?: Partial<RateTerms>;
8897
+ availability?: Partial<AvailabilityTerms>;
8898
+ }
8899
+ interface SupplyTermSheet {
8900
+ /** Is this position earning, or is it just collateral? */
8901
+ role: Open<'yield' | 'collateral' | 'both'>;
8902
+ rate: RateTerms;
8903
+ maturity: MaturityTerms;
8904
+ exit: SupplyExitTerms;
8905
+ /** ALL fees on this side, including the exit subset. */
8906
+ fees: FeeTerm[];
8907
+ /** What secures the debt drawn against this deposit. */
8908
+ backedBy?: ExposureTerms;
8909
+ modes?: ModeVariant[];
8910
+ counterparty: CounterpartyTerms;
8911
+ availability: AvailabilityTerms;
8912
+ /** Is the supplied principal at risk beyond ordinary credit risk? */
8913
+ principal: {
8914
+ protected: boolean;
8915
+ risks: Open<'bad-debt' | 'physical-delivery' | 'nav-drawdown' | 'first-loss' | 'depeg'>[];
8916
+ };
8917
+ info: TermInfo;
8918
+ /** Namespaced escape hatch — see the promotion rule in TERM_SHEET_PLAN §13.5. */
8919
+ ext?: Record<string, unknown>;
8920
+ }
8921
+ interface BorrowTermSheet {
8922
+ rate: RateTerms;
8923
+ maturity: MaturityTerms;
8924
+ /**
8925
+ * Does the amount owed GROW, or is it a static face value fixed at trade
8926
+ * time? The single biggest departure from variable-rate intuition — four of
8927
+ * six fixed-term lenders are static.
8928
+ */
8929
+ debtShape: Open<'accruing' | 'static-face' | 'prepaid'>;
8930
+ exit: BorrowExitTerms;
8931
+ /** Fully resolved for the DEFAULT mode. `modes[]` carries the rest. */
8932
+ liquidation: LiquidationTerms;
8933
+ /** What you may post, each with its own LTV, oracle and quality. */
8934
+ acceptedCollateral?: ExposureTerms;
8935
+ modes?: ModeVariant[];
8936
+ fees: FeeTerm[];
8937
+ counterparty: CounterpartyTerms;
8938
+ availability: AvailabilityTerms;
8939
+ info: TermInfo;
8940
+ ext?: Record<string, unknown>;
8941
+ }
8942
+ /**
8943
+ * Distinguishes "not applicable" from "not implemented yet" — the affordance
8944
+ * that lets phases ship incrementally without lying. A missing `oracle` must
8945
+ * never read as "this market has no oracle" when the truth is "we have not
8946
+ * classified it".
8947
+ */
8948
+ interface CoverageInfo {
8949
+ /** Blocks genuinely computed for this market. */
8950
+ present: string[];
8951
+ /** Blocks that do NOT APPLY here — a positive fact. */
8952
+ notApplicable?: Record<string, string>;
8953
+ /** Blocks that WOULD apply but are not wired yet. */
8954
+ pending?: Record<string, string>;
8955
+ }
8956
+ /** Current schema version. Bumped ONLY for removals/semantic/unit changes;
8957
+ * new optional fields and new enum members are additive. */
8958
+ declare const TERM_SHEET_SCHEMA_VERSION = 1;
8959
+ interface TermSheet {
8960
+ schemaVersion: number;
8961
+ /** unix seconds at fetch — everything here is a snapshot. */
8962
+ asOf: number;
8963
+ /** `<family>.<variant>@v<n>`, e.g. `aave-v3.pool@v1`. Points at the prose
8964
+ * catalogue so the per-market payload stays small. */
8965
+ profileId: string;
8966
+ /** The anchor this sheet describes. */
8967
+ marketUid?: string;
8968
+ lender?: string;
8969
+ chainId?: string;
8970
+ supply?: SupplyTermSheet;
8971
+ borrow?: BorrowTermSheet;
8972
+ /** Shared — these describe the MARKET, not a side. */
8973
+ governance?: GovernanceTerms;
8974
+ oracle?: OracleTerms;
8975
+ utilization?: UtilizationTerms;
8976
+ constraints?: PositionConstraints;
8977
+ coverage?: CoverageInfo;
8978
+ ext?: Record<string, unknown>;
8979
+ }
8980
+ /** Compact form for list endpoints — `?terms=digest`. */
8981
+ interface TermSheetDigest {
8982
+ schemaVersion: number;
8983
+ profileId: string;
8984
+ marketUid?: string;
8985
+ supply?: {
8986
+ rateKind: RateKind;
8987
+ aprTotal: AprPercent;
8988
+ maturityKind: MaturityTerms['kind'];
8989
+ maturity?: number;
8990
+ exitMode: SupplyExitMode;
8991
+ settlement: SupplyExitTerms['settlement'];
8992
+ canOpen: boolean;
8993
+ headline: string;
8994
+ tags: TermTag[];
8995
+ backedBy?: Omit<ExposureTerms, 'items'>;
8996
+ };
8997
+ borrow?: {
8998
+ rateKind: RateKind;
8999
+ apr: AprPercent;
9000
+ maturityKind: MaturityTerms['kind'];
9001
+ maturity?: number;
9002
+ debtShape: BorrowTermSheet['debtShape'];
9003
+ earlyRepay: BorrowExitTerms['earlyRepay'];
9004
+ liquidationTrigger: LiquidationTerms['trigger'];
9005
+ canOpen: boolean;
9006
+ headline: string;
9007
+ tags: TermTag[];
9008
+ acceptedCollateral?: Omit<ExposureTerms, 'items'>;
9009
+ };
9010
+ oracle?: Pick<OracleTerms, 'kind' | 'address' | 'provider' | 'band'>;
9011
+ governance?: Pick<GovernanceTerms, 'mutability' | 'controllerKind' | 'timelockSecs' | 'tier'>;
9012
+ utilization?: number;
9013
+ }
9014
+ /** A term profile — the invariant prose, one per lender family × variant. */
9015
+ interface TermProfile {
9016
+ id: string;
9017
+ /** Display name, e.g. `Aave V3 pool market`. */
9018
+ name: string;
9019
+ /** Which lender family this covers. */
9020
+ family: string;
9021
+ supply?: {
9022
+ description: string;
9023
+ implications?: string[];
9024
+ };
9025
+ borrow?: {
9026
+ description: string;
9027
+ implications?: string[];
9028
+ };
9029
+ docsUrl?: string;
9030
+ }
9031
+ /** Deep-partial, for adapters that return only what they override. */
9032
+ type DeepPartial<T> = {
9033
+ [K in keyof T]?: T[K] extends (infer U)[] ? U[] : T[K] extends object | undefined ? DeepPartial<NonNullable<T[K]>> : T[K];
9034
+ };
9035
+
9036
+ /**
9037
+ * The normalized input the builder reads.
9038
+ *
9039
+ * Deliberately NOT `PoolData` directly: the same market travels through this
9040
+ * codebase in two casings — the in-package shape (`totalDepositsUSD`,
9041
+ * `variableBorrowRate`) and the API-serialized shape (`totalDepositsUsd`,
9042
+ * nested `caps`/`flags`/`config`). The builder must work on both, because it
9043
+ * runs in-package during a fetch AND at the worker while proxying an origin
9044
+ * response.
9045
+ *
9046
+ * So: one tolerant reader (`toTermSheetInput`) normalizes either shape into
9047
+ * this interface, and the builder itself is pure over the normalized form.
9048
+ */
9049
+ interface TermConfigEntry {
9050
+ category: number | string;
9051
+ label?: string;
9052
+ borrowCollateralFactor?: number;
9053
+ collateralFactor?: number;
9054
+ borrowFactor?: number;
9055
+ liquidationPenalty?: number;
9056
+ closeFactor?: number;
9057
+ targetHealthFactor?: number;
9058
+ collateralDisabled?: boolean;
9059
+ debtDisabled?: boolean;
9060
+ }
9061
+ interface TermRewardInput {
9062
+ asset?: string;
9063
+ depositRate?: number;
9064
+ variableBorrowRate?: number;
9065
+ stableBorrowRate?: number;
9066
+ /** Merkl / points programs mark themselves; absent ⇒ a normal token. */
9067
+ kind?: string;
9068
+ endsAt?: number;
9069
+ claim?: string;
9070
+ }
9071
+ interface TermMenuInput {
9072
+ termId: number;
9073
+ durationSecs: number;
9074
+ durationDays: number;
9075
+ apr: number;
9076
+ depositApr?: number;
9077
+ available?: number;
9078
+ }
9079
+ /** Normalized market facts the generic builder needs. */
9080
+ interface TermSheetInput {
9081
+ marketUid: string;
9082
+ lender: string;
9083
+ chainId: string;
9084
+ /** Underlying asset of THIS row. */
9085
+ asset?: {
9086
+ chainId?: string;
9087
+ address?: string;
9088
+ symbol?: string;
9089
+ name?: string;
9090
+ decimals?: number;
9091
+ assetGroup?: string;
9092
+ logoURI?: string;
9093
+ };
9094
+ underlying?: string;
9095
+ decimals?: number;
9096
+ depositRate?: number;
9097
+ variableBorrowRate?: number;
9098
+ stableBorrowRate?: number;
9099
+ intrinsicYield?: number;
9100
+ rewards?: TermRewardInput[];
9101
+ rateModel?: string;
9102
+ originationFee?: number;
9103
+ totalDeposits?: number;
9104
+ totalDebt?: number;
9105
+ totalDebtStable?: number;
9106
+ totalLiquidity?: number;
9107
+ borrowLiquidity?: number;
9108
+ totalDepositsUsd?: number;
9109
+ totalDebtUsd?: number;
9110
+ totalLiquidityUsd?: number;
9111
+ utilization?: number;
9112
+ irmTotalDeposits?: number;
9113
+ irmTotalDebt?: number;
9114
+ lockupRatio?: number;
9115
+ supplyCap?: number;
9116
+ borrowCap?: number;
9117
+ debtCeiling?: string | number;
9118
+ isActive?: boolean;
9119
+ isFrozen?: boolean;
9120
+ borrowingEnabled?: boolean;
9121
+ depositsEnabled?: boolean;
9122
+ collateralActive?: boolean;
9123
+ hasStable?: boolean;
9124
+ variableBorrowDisabled?: boolean;
9125
+ config?: Record<string, TermConfigEntry>;
9126
+ closeFactor?: number;
9127
+ targetHealthFactor?: number;
9128
+ fixedTerm?: {
9129
+ model?: string;
9130
+ maturity?: number;
9131
+ fees?: {
9132
+ continuousFeeApr?: number;
9133
+ settlementFee?: number;
9134
+ latePenaltyApr?: number;
9135
+ originationFeePercent?: number;
9136
+ };
9137
+ earlyRepay?: {
9138
+ kind?: string;
9139
+ };
9140
+ provider?: {
9141
+ kind?: string;
9142
+ address?: string;
9143
+ };
9144
+ auction?: Record<string, unknown>;
9145
+ };
9146
+ terms?: TermMenuInput[];
9147
+ /** Market-level params (`params.market`) when the lender has them. */
9148
+ market?: Record<string, unknown>;
9149
+ }
9150
+ /**
9151
+ * Normalize either the in-package `PoolData`-ish row or an API `LendingMarket`
9152
+ * item into {@link TermSheetInput}. Tolerant by design: a field missing under
9153
+ * one casing is looked up under the other, and nested `caps`/`flags` bundles
9154
+ * are unwrapped.
9155
+ */
9156
+ declare function toTermSheetInput(row: Record<string, any>, ctx?: {
9157
+ marketUid?: string;
9158
+ lender?: string;
9159
+ chainId?: string;
9160
+ market?: Record<string, any>;
9161
+ /**
9162
+ * Item-level fixed-term descriptor. `/lending/latest` attaches `fixedTerm`
9163
+ * to the LENDER item, not to each market row, so without this every
9164
+ * fixed-term market would silently lose its maturity, its fees and its
9165
+ * auction window. A row-level `fixedTerm` (how `/pools/latest` serializes
9166
+ * it) is more specific and wins.
9167
+ */
9168
+ fixedTerm?: Record<string, any>;
9169
+ }): TermSheetInput;
9170
+
9171
+ /**
9172
+ * Accepted-collateral / backing set from the SIBLING rows of the same lender.
9173
+ *
9174
+ * Pooled lenders (Aave, Compound) do NOT record on-chain which collateral
9175
+ * backs which borrow, so the result is the ACCEPTED SET with
9176
+ * `weightBasis: 'unweighted'` and NO `weightPct` on any item. Inventing a
9177
+ * TVL-proxy weight would look authoritative and be false — a large idle
9178
+ * collateral market is not a large exposure.
9179
+ */
9180
+ declare function buildExposures(input: TermSheetInput, siblings: TermSheetInput[], direction: 'backing' | 'accepted'): ExposureTerms | undefined;
9181
+ /** Deep merge an adapter's partial over the generic result. Arrays REPLACE. */
9182
+ declare function mergeDeep<T>(base: T, patch: DeepPartial<T> | undefined): T;
9183
+ /**
9184
+ * Fill `info` (headline / description / tags) LAST, after adapters have run,
9185
+ * so the prose always describes the final values rather than the generic
9186
+ * guess. This is the mechanism that stops copy drifting from numbers.
9187
+ */
9188
+ declare function finalizeInfo(sheet: TermSheet): TermSheet;
9189
+ interface BuildTermSheetOptions {
9190
+ /** Unix seconds; injected so tests are deterministic. */
9191
+ now?: number;
9192
+ /** Other rows of the SAME lender+chain — used to derive the exposure set. */
9193
+ siblings?: TermSheetInput[];
9194
+ /** Adapter output, merged over the generic result. */
9195
+ patch?: DeepPartial<TermSheet>;
9196
+ profileId?: string;
9197
+ }
9198
+ /** Build one complete term sheet for one market row. */
9199
+ declare function buildTermSheet(input: TermSheetInput, opts?: BuildTermSheetOptions): TermSheet;
9200
+
9201
+ /** Supply-side tags. Market-level tags are folded in by the caller. */
9202
+ declare function deriveSupplyTags(supply: SupplyTermSheet, market?: Pick<TermSheet, 'governance' | 'oracle'>): TermTag[];
9203
+ /** Borrow-side tags. */
9204
+ declare function deriveBorrowTags(borrow: BorrowTermSheet, market?: Pick<TermSheet, 'governance' | 'oracle'>): TermTag[];
9205
+
9206
+ /**
9207
+ * Severity model — PURE, derived only from structured fields.
9208
+ *
9209
+ * Space is the binding constraint at every display depth, so ranking has to be
9210
+ * principled rather than per-lender taste. There is deliberately NO
9211
+ * hand-maintained list of "scary markets": a newly integrated lender is
9212
+ * classified correctly the moment its adapter sets the right fields.
9213
+ *
9214
+ * - `critical` — you can lose MORE than the amount at stake, or lose it
9215
+ * without doing anything wrong. This is the only tier that should gate a
9216
+ * signature.
9217
+ * - `warn` — it costs money, or blocks you.
9218
+ * - `info` — everything else.
9219
+ */
9220
+ type Severity = 'critical' | 'warn' | 'info';
9221
+ interface SeverityFinding {
9222
+ severity: Severity;
9223
+ /** Stable slug — the join key for UI copy and for tests. */
9224
+ id: string;
9225
+ /** Ready-to-render sentence. */
9226
+ message: string;
9227
+ side: 'supply' | 'borrow' | 'market';
9228
+ }
9229
+ /** Sort findings most-severe-first, stable within a tier. */
9230
+ declare function rankFindings(findings: SeverityFinding[]): SeverityFinding[];
9231
+ declare function supplyFindings(supply: SupplyTermSheet): SeverityFinding[];
9232
+ declare function borrowFindings(borrow: BorrowTermSheet): SeverityFinding[];
9233
+ /**
9234
+ * All findings for one side of a sheet, ranked most-severe-first. Pass
9235
+ * `side: 'supply' | 'borrow'` — market-level findings are always included
9236
+ * because governance and oracle affect both sides.
9237
+ */
9238
+ declare function findingsFor(sheet: TermSheet, side: 'supply' | 'borrow'): SeverityFinding[];
9239
+ /** Does this side carry anything that should gate a signature? */
9240
+ declare function hasCritical(sheet: TermSheet, side: 'supply' | 'borrow'): boolean;
9241
+
9242
+ /** `4.1234` → `"4.12 %"`; trims to 2dp, drops a trailing `.00`. */
9243
+ declare function pct(value: number | undefined, dp?: number): string;
9244
+ /** Duration in seconds → the coarsest human unit that stays honest. */
9245
+ declare function duration(secs: number | undefined): string;
9246
+ /** Unix seconds → `"3 Sep 2026"`. Locale-independent so snapshots are stable. */
9247
+ declare function shortDate(unixSecs: number | undefined): string;
9248
+ /** One fee → a self-contained phrase, correct even for an unrecognised `id`. */
9249
+ declare function feePhrase(fee: FeeTerm): string;
9250
+ /** Supply-side headline: ≤ ~100 chars, always populated. */
9251
+ declare function supplyHeadline(s: SupplyTermSheet): string;
9252
+ /** Borrow-side headline. */
9253
+ declare function borrowHeadline(b: BorrowTermSheet): string;
9254
+ /** Supply-side description — 1–3 sentences, market values interpolated. */
9255
+ declare function supplyDescription(s: SupplyTermSheet, sheet?: Pick<TermSheet, 'utilization'>): string;
9256
+ /** Borrow-side description. */
9257
+ declare function borrowDescription(b: BorrowTermSheet): string;
9258
+
9259
+ declare const TERM_PROFILES: TermProfile[];
9260
+ declare function getTermProfile(id: string): TermProfile | undefined;
9261
+ /** Fallback used when a family has no dedicated profile yet. */
9262
+ declare const DEFAULT_PROFILE_ID = "pool.variable@v1";
9263
+
9264
+ /**
9265
+ * Stamping — the single place term sheets are attached.
9266
+ *
9267
+ * Runs ONCE at the end of the public-data pipeline rather than inside each
9268
+ * lender's converter. That is the whole architecture: ~200 Aave/Compound forks
9269
+ * get correct sheets from the generic builder with zero per-fork work, and
9270
+ * only the ~13 exotic families need an adapter.
9271
+ */
9272
+ interface StampOptions {
9273
+ /** Unix seconds; injected so tests are deterministic. */
9274
+ now?: number;
9275
+ /** Attach ranked `implications[]` from the severity model. Default true. */
9276
+ withImplications?: boolean;
9277
+ /**
9278
+ * Derive `governance` / `oracle` / exposure quality from the rows' own
9279
+ * `oracleInfo` + `risk.breakdown`. Default true — set `false` only to test
9280
+ * the un-enriched builder in isolation.
9281
+ */
9282
+ enrich?: boolean;
9283
+ }
9284
+ /**
9285
+ * Build sheets for one lender's rows on one chain.
9286
+ *
9287
+ * Siblings matter: the exposure set (`backedBy` / `acceptedCollateral`) is
9288
+ * derived by cross-referencing the OTHER rows of the same lender, so the whole
9289
+ * group has to be built together.
9290
+ */
9291
+ declare function buildTermSheetsForGroup(rows: Record<string, any>[], ctx?: {
9292
+ lender?: string;
9293
+ chainId?: string;
9294
+ market?: Record<string, any>;
9295
+ /** Item-level `fixedTerm` from `/lending/latest` — see `toTermSheetInput`. */
9296
+ fixedTerm?: Record<string, any>;
9297
+ }, opts?: StampOptions): Map<string, TermSheet>;
9298
+ /**
9299
+ * Fill `info.implications[]` from the severity model, most severe first.
9300
+ *
9301
+ * Derived rather than hand-written, so a newly integrated lender gets correct
9302
+ * warnings the moment its adapter sets the right structured fields — and a
9303
+ * warning can never contradict the numbers next to it.
9304
+ */
9305
+ declare function attachImplications(sheet: TermSheet): TermSheet;
9306
+ /**
9307
+ * Build an {@link EnrichmentIndex} from the market rows themselves.
9308
+ *
9309
+ * The governance and oracle screens are NOT a separate fetch: the origin
9310
+ * already ships both on every row — `oracleInfo.feeds[]` (the oracle-risk
9311
+ * classification) and `risk.breakdown[]` (the governance screen under
9312
+ * `category: 'governance'`, the asset screen under `category: 'token'`). So
9313
+ * the join is local to the group being stamped, with no extra round-trip and
9314
+ * no cross-service dependency.
9315
+ *
9316
+ * The per-exposure enrichment falls out of the same data: an exposure item
9317
+ * points at a SIBLING row's `marketUid`, and that sibling is already in this
9318
+ * group — so its oracle and its asset quality are right there.
9319
+ */
9320
+ declare function enrichmentIndexFromRows(rows: Record<string, any>[]): EnrichmentIndex;
9321
+ /**
9322
+ * Collapse a sheet to its digest form (`?terms=digest`).
9323
+ *
9324
+ * Drops `items[]` from the exposure sets and the long prose — an Aave market
9325
+ * with 30 accepted collaterals is several kB on its own, and it is the SAME
9326
+ * accepted set repeated on every row of that lender. Every dropped item is
9327
+ * still reachable: each carries a `marketUid` for the bulk endpoint.
9328
+ */
9329
+ declare function toDigest(sheet: TermSheet): TermSheetDigest;
9330
+ /** Row shape of `~/risk-data/data/oracles/oracle-risk-flat.json`. */
9331
+ interface OracleRiskRow {
9332
+ marketUid: string;
9333
+ oracle?: string;
9334
+ provider?: string;
9335
+ priceDescription?: string;
9336
+ intendedPair?: string;
9337
+ correctOracle?: boolean | null;
9338
+ denominatorMatch?: boolean | null;
9339
+ fixedRate?: boolean;
9340
+ score?: number;
9341
+ band?: string;
9342
+ flags?: string[];
9343
+ /** Underlying feeds when an adapter composes several. `oracle` stays the
9344
+ * single source of truth — this is for auditability only. */
9345
+ components?: string[];
9346
+ }
9347
+ /** Row shape of `~/risk-data/data/lending/market-governance-flat.json`. */
9348
+ interface GovernanceRow {
9349
+ marketUid: string;
9350
+ tier?: string;
9351
+ score?: number;
9352
+ ownerKind?: string;
9353
+ signerThreshold?: number | null;
9354
+ signerCount?: number | null;
9355
+ mode?: string;
9356
+ /** Present once the flat builder carries it through (see TERM_SHEET_PLAN §5.4.1). */
9357
+ delaySeconds?: number | null;
9358
+ }
9359
+ /** Per-asset quality, keyed `chainId → lowercased address`. */
9360
+ type AssetRiskIndex = Record<string, Record<string, {
9361
+ riskScore?: number;
9362
+ source?: string;
9363
+ liquidityUsd?: number;
9364
+ governanceScore?: number;
9365
+ governanceLevel?: string;
9366
+ upgradeable?: boolean;
9367
+ canPause?: boolean;
9368
+ adminKind?: string;
9369
+ }>>;
9370
+ interface EnrichmentIndex {
9371
+ oracleByMarketUid?: Map<string, OracleRiskRow>;
9372
+ governanceByMarketUid?: Map<string, GovernanceRow>;
9373
+ assetRisk?: AssetRiskIndex;
9374
+ }
9375
+ /**
9376
+ * Merge governance / oracle / asset-quality onto a sheet at the SERVING layer.
9377
+ *
9378
+ * These cannot be computed in-package — they come from the risk-data
9379
+ * screeners, which key on the same `marketUid` grammar (a dictionary lookup,
9380
+ * not a fuzzy match). `margin-fetcher` emits the sheet with these blocks
9381
+ * absent; the worker fills them in, exactly as it already does for
9382
+ * `oracleInfo`.
9383
+ */
9384
+ declare function enrichTermSheet(sheet: TermSheet, index: EnrichmentIndex): TermSheet;
9385
+
9386
+ /**
9387
+ * Invariant checker — pure, and the mechanism that turns a derivation bug into
9388
+ * a loud failure instead of a plausible-looking wrong answer.
9389
+ *
9390
+ * Run over live fetched data in CI for every lender key and vault provider.
9391
+ * Every rule here encodes something that WOULD otherwise ship silently.
9392
+ */
9393
+ interface TermSheetViolation {
9394
+ /** Stable slug, so a test can assert on the specific rule. */
9395
+ rule: string;
9396
+ message: string;
9397
+ marketUid?: string;
9398
+ }
9399
+ declare function validateTermSheet(sheet: TermSheet): TermSheetViolation[];
9400
+ /** Validate a batch; returns every violation found, flattened. */
9401
+ declare function validateTermSheets(sheets: TermSheet[]): TermSheetViolation[];
9402
+
9403
+ /**
9404
+ * A term-sheet adapter: returns ONLY what the generic builder cannot derive,
9405
+ * as a `DeepPartial<TermSheet>` merged over the generic result.
9406
+ *
9407
+ * Adding a lender is one adapter plus one profile entry — no core edits. The
9408
+ * completeness test fails when a lender family reaches production without a
9409
+ * profile, so the extension point cannot be silently skipped.
9410
+ */
9411
+ interface TermAdapter {
9412
+ /** Stable id, for tests and debugging. */
9413
+ id: string;
9414
+ /** Does this adapter handle the given lender key? */
9415
+ matches: (lender: string) => boolean;
9416
+ /** The profile whose prose this market points at. */
9417
+ profileId: (input: TermSheetInput) => string;
9418
+ build: (input: TermSheetInput) => DeepPartial<TermSheet>;
9419
+ }
9420
+ /**
9421
+ * Order matters only where predicates could overlap; today they are disjoint.
9422
+ * The list is walked front-to-back and the first match wins.
9423
+ */
9424
+ declare const TERM_ADAPTERS: TermAdapter[];
9425
+ declare function resolveAdapter(lender: string): TermAdapter | undefined;
9426
+
9427
+ export { type AaveMetadata, type AaveV2Public, type AaveV2UserReserveResponse, type AaveV3Public, type AaveV3UserReserveResponse, type AdditionalYields, type AdminKind, ApiBookSource, type AprData, type AprPercent, type AssetQuality, type AssetRiskIndex, type AuctionWindow, type AvailabilityTerms, type BalanceData, type BaseLendingPosition, type BasicReserveResponse, type BorrowExitTerms, type BorrowTermSheet, type BuildTermSheetOptions, type ChainDiagnostic, type ChainLinkResponse, type ChainQuery, type ChainSummary, type CompoundV2Metadata, type CompoundV3Public, type CompoundV3UserReserveResponse, type ConfigEntry, type ConvertLenderUserDataOptions, type CoreValidators, type CounterpartyTerms, type CoverageInfo, DEFAULT_MIDNIGHT_API, DEFAULT_OUTLIER_GUARD, DEFAULT_PROFILE_ID, DEFAULT_STALE_REJECT_SECONDS, DEFAULT_TERMMAX_API, type DeepPartial, type Denomination, type DepthMap, EMPTY_BALANCE, type EModeAssets, type EModeData, type EModeResult, EXACTLY_LENDER_KEY, type EndpointFailure, type EnrichmentIndex, type EulerEarnVault, type EulerEarnVaults, type EulerV2Metadata, type ExactlyFixedPool, type ExactlyFixedPosition, type ExactlyMarketAccount, type ExactlyMarketsRaw, type ExactlyUserFixedPosition, type ExposureEntry, type ExposureTerms, type ExtraValidationCall, type FeeTerm, type FeeWhen, type FeedObservation, type FeedStat, type FeedStatsMap, type FeedTimestampMap, type FetchListaVaultsFromChainOptions, type FetchMorphoVaultsFromChainOptions, type FetchOraclePricesOptions, type FetchTokenBalancesOptions, type FlattenPriorityConfig, type FluidFToken, type FluidFTokens, type FrankencoinMarketRaw, type FrankencoinMarketsRaw, type FrankencoinPositionInfo, type FullLenderRewardsMap, GMX_API_HOSTS, GMX_READ_CONTRACTS, GMX_SUPPORTED_CHAINS, type GenericCurrency, type GenericTokenList, type GetVaultPublicDataAllOptions, type GmxExecutionFees, type GmxPendingDeposit, type GmxPendingWithdrawal, type GmxReadContracts, type GmxUserBalance, type GmxUserPositions, type GmxUserPositionsOptions, type GmxVault, type GmxVaultKind, type GmxVaults, type GmxVaultsFetchOptions, type GovernancePower, type GovernanceRow, type GovernanceTerms, type GroupAccumulator, HYPERCORE_VAULT_REGISTRY, type HypercoreLockStatus, type HypercoreUserPositionsOptions, type HypercoreVault, type HypercoreVaultPosition, type HypercoreVaultRegistryEntry, type HypercoreVaults, type HypercoreVaultsFetchOptions, IDLE_MARKET_ID, INTERFACE_IDS, type IncompleteLenderRead, type IncompleteReason, type InitMetadata, type InitPublic, type InitUserReserveResponse, type InterfaceKind, type InvariantViolation, type InverseMarketRaw, type InverseMarketsRaw, type InversePositionInfo, LAGOON_API_URL, LAGOON_CHAIN_IDS, type LagoonApiVault, type LagoonSyncMode, type LagoonVault, type LagoonVaults, type LenderConfigData, type LenderConfigMap, type LenderCrossPoolMeta, type LenderData, type LenderDataEntry, type LenderInfo, type LenderInfoMap, type LenderPublicBase, type LenderRewardsMap, type LenderSummary, type LenderToLenderCrossPoolMeta, type LenderTotalAmounts, type LenderUserQuery, type LenderUserResponse, type LenderYieldComplete, type LenderYields$1 as LenderYields, LendingMode, type LiquidationTerms, type LiquityBranchRaw, type LiquityDiscoveredTrove, type LiquityDiscovery, type LiquityMarketsRaw, type LiquitySpInfo, type LiquityTroveInfo, type ListaMarketOverrides, type LlamaLendMarketRaw, type LlamaLendMarketsRaw, type LlamaLendPositionInfo, type LoopPostTradeMetrics, type LstDelegation, type LstDelegationKind, type LstValidator, type LstWithdrawalFetchOptions, type LstWithdrawalRegistryEntry, type LstWithdrawalRequest, type LstWithdrawalRequestsByLst, type LstWithdrawalStatus, MORPHO_LENS, MULTICALL_FAILURE, type MaturityTerms, MaxParamThresholds, type MergedUserData, type MidnightBook, type MidnightBookLevel, type MidnightBookSource, type ModeBase, type ModeVariant, type MorphoMarketOverrides, type MorphoSubgraphProxyConfig, type MorphoUserMarketBalance, type MorphoUserReserveResponse, type MorphoVault, type MorphoVaults, type MulticallEndpointOptions, type MulticallRpcBatch, type NumberMap, type Open, type OracleBand, type OracleDiagnostics, type OraclePriceEntry, type OraclePricesResult, type OracleRiskRow, type OracleTerms, type OutlierGuardConfig, type ParsedBalanceData, type ParsedResponse, type ParsedUserBalance, type PermissionKind, type PermissionParams, type PoolData, type PoolWithMeta, type PortfolioSummary, type PortfolioTotals, type PositionConstraints, type PostTradeMetrics, type PreparedCall, type PreparedMergedMulticallParams, type PreparedMergedRpcCalls, type PreparedTokenBalanceRpcCalls, type PreparedUserDataRpcCalls, type PriceDerivation, type PriceSelection, type ProtocolParams, type ProviderOptions, type RateKind, type RateMenuEntry, type RateTerms, type RawRpcBatch, type RawRpcCall, type RawRpcResponse, type ReadFailurePolicy, type ResupplyMarketsRaw, type ResupplyPairIdentity, type ResupplyPairRaw, type ResupplyPositionInfo, type ResupplyWrappedMarket, type RewardTerm, type RiverMarketRaw, type RiverMarketsRaw, type RiverPositionInfo, STABLECOIN_SYMBOLS, STCELO_MANAGER_ADDRESS, type SelectPricesOptions, type Severity, type SeverityFinding, type SiloVault, type SiloVaults, type StCeloValidatorGroup, type StaleFeedEntry, type StampOptions, type StructuredOraclePrices, type SubAccountSummary, type SumerPositionInput, type SummaryAprData, type SummaryBalanceData, type SupplyExitMode, type SupplyExitTerms, type SupplyTermSheet, TELLER_CALLS_PER_BID, TERMMAX_CALLS_PER_ACCOUNT, DECIMAL_BASE as TERMMAX_DECIMAL_BASE, TERMMAX_LIQUIDATION_PENALTY, TERMMAX_LIQUIDATION_WINDOW_SECS, TERMMAX_LIQUIDATOR_BONUS, TERMMAX_PARTIAL_CLOSE_FACTOR, TERMMAX_PARTIAL_LIQUIDATION_THRESHOLD_USD, TERM_ADAPTERS, TERM_PROFILES, TERM_SHEET_SCHEMA_VERSION, type TellerDiscoveredBid, type TellerDiscovery, type TellerMarketsRaw, type TellerPoolRaw, type TermAdapter, type TermAssetRef, type TermAuctionOrder, type TermAuctionOrders, type TermBookSource, type TermBookTop, type TermInfo, type TermListing, type TermMarketRaw, TermMaxApiSource, type TermMaxBookTop, type TermMaxCurveSegment, type TermMaxDataSource, type TermMaxDiscovery, type TermMaxFeeConfig, type TermMaxMarketConfig, type TermMaxMarketRaw, type TermMaxOrderState, type TermProfile, type TermSheet, type TermSheetDigest, type TermSheetInput, type TermSheetViolation, TermSubgraphSource, type TermTag, type TokenApprovalMeta, type TokenApprovalParams, type TokenBalanceEntry, type TokenBalanceQuery, type TokenBalanceResult, type TokenEntry, type TokenList, type TokenListInput, type TrackerDiagnostic, UPSHIFT_CHAIN_IDS, UPSHIFT_VAULTS_URL, type USDPriceMap, type UpshiftApiAsset, type UpshiftApiVault, type UpshiftVault, type UpshiftVaults, type UsddMarketRaw, type UsddMarketsRaw, type UsddPositionInfo, type UserApr, type UserConfig, type UserData, type UserDataResult, type UserLendingPosition, type UtilizationTerms, VAULT_SHARE_PRICE_PROBE, VOLATILE_VAULT_OVERRIDES, type ValidationResult, type VaultAprResult, type VaultClassification, type VaultClassificationFields, type VaultLookupEntry, type VaultMarketExposure, type VaultProvider, type VaultPublicDataAll, type VaultPublicDataResult, type VaultYieldSeries, type VaultYieldSnapshot, type YDaemonVault, YEARN_CHAIN_IDS, YEARN_YDAEMON_BASE, type YearnVault, type YearnVaultKind, type YearnVaults, type YieldProfile, __resetResupplyUserCaches, accountDepositListKey, accountWithdrawalListKey, appendSnapshot, applyPositionDelta, attachImplications, attachPricesToFlashLiquidity, borrowDescription, borrowFindings, borrowHeadline, buildExposures, buildFluidFTokensCall, buildLiquityUserCall, buildLoopResult, buildMorphoTypeCall, buildMorphoTypeUserCallWithLens, buildPortfolioTotals, buildSumerAccumulators, buildSummaries, buildTellerUserCall, buildTermMaxUserCall, buildTermSheet, buildTermSheetsForGroup, buildVaultLookup, calculateLeverage, calculateNetApr, calculateOverallNetApr, calculateWeightedAverage, classifyFreshness, classifyReliability, classifyVault, collectFeedObservations, computeBorrowDelta, computeCloseTradeDeltas, computeCollateralSwapDeltas, computeDebtSwapDeltas, computeDepositDelta, computeEModeAnalysis, computeOpenTradeDeltas, computePostTradeMetrics, computeRepayDelta, computeSumerBorrowDelta, computeSumerDepositDelta, computeSumerRepayDelta, computeSumerWaterfall, computeSumerWithdrawDelta, computeVaultApr, computeWithdrawDelta, computeZapTradeDeltas, consensusReference, convertExactlyMarketsToResponse, convertFrankencoinMarketsToResponse, convertInverseMarketsToResponse, convertLenderUserDataResult, convertLiquityMarketsToResponse, convertLlamaLendMarketsToResponse, convertResupplyMarketsToResponse, convertRiverMarketsToResponse, convertTellerMarketsToResponse, convertTermMarketsToResponse, convertTermMaxMarketsToResponse, convertUsddMarketsToResponse, createMarketUid, createMidnightBookSource, createMulticallRpcCall, createRawRpcCalls, createTermBookSource, createTermMaxDataSource, decodeListaMarkets, decodeMarkets, decodePackedListaUserDataset, decodePackedMorphoUserDataset, deriveBorrowTags, deriveSupplyTags, detectInterfaceKinds, duration, encodeBalanceFetcherCalldata, enrichTermSheet, enrichmentIndexFromRows, exactlyPairLtv, exactlyPenaltyRateToAprPercent, exactlyWadRateToPercent, feePhrase, feedKeyOf, feedStatKey, fetchDolomiteAccountNumbers, fetchEulerEarnVaults, fetchEulerEarnVaultsFromSubgraph, fetchEulerSubAccountIndexes, fetchExactlyMarkets, fetchFlashLiquidityForChain, fetchFluidFTokens, fetchFrankencoinMarkets, fetchGeneralYields, fetchGeneralYieldsByMarketUid, fetchGmxExecutionFees, fetchGmxTickerPrices, fetchGmxVaults, fetchHypercoreVaults, fetchInverseMarkets, fetchLagoonApiVaults, fetchLagoonVaults, fetchLiquityMarkets, fetchListaVaultsFromChain, fetchLlamaLendMarkets, fetchMorphoUserBalances, fetchMorphoUserPositionMarkets, fetchMorphoVaults, fetchMorphoVaultsFromApi, fetchMorphoVaultsFromChain, fetchOraclePrices, fetchPendlePrices, fetchResupplyMarkets, fetchRiverMarkets, fetchSiloVaults, fetchTellerMarkets, fetchTermMarkets, fetchTermMaxMarkets, fetchTokenBalances, fetchTokenMetadata, fetchUpshiftApiVaults, fetchUpshiftVaults, fetchUsddMarkets, fetchYearnApiVaults, fetchYearnVaults, filterActiveLenders, filterLendersByProtocol, finalizeInfo, findingsFor, frankencoinKeyParts, frankencoinLenderKey, fuseLenderData, generateLendingPools, getAavesForChain, getAssetConfig, getBalanceForMarketUid, getBorrowCapacity, getCachedLiquityTroves, getCachedTellerBids, getCachedTermMaxDiscovery, getCachedTermMaxMarket, getCachedTermMaxMarkets, getCoreValidators, getFluidFTokensConverter, getGmxApiHost, getGmxReadContracts, getGmxUserPositions, getHealthFactor, getHypercoreUserPositions, getHypercoreVaultRegistry, getLenderAssets, getLenderPublicData, getLenderPublicDataAll, getLenderPublicDataViaApi, getLenderUserDataMulti, getLenderUserDataResult, getLendersForChain, getLstDelegation, getLstValidators, getLstWithdrawalRegistry, getLstWithdrawalRequests, getMaxAmountClose, getMaxAmountCollateralSwap, getMaxAmountDebtSwap, getMaxAmountOpen, getMergedUserData, getMorphoTypeMarketConverter, getReadFailurePolicy, getResolvedDolomiteAccountNumbers, getStCeloValidatorGroups, getSubAccountAddress, getSubAccountIndex, getTermProfile, getVaultPublicDataAll, getVaultWithdrawalRequests, hasCritical, hasEulerEarnVaultSubgraph, hasLagoonVaults, hasMorphoPositionIndex, hasMorphoUserApi, hasMorphoUserSubgraph, hasUpshiftVaults, hasYearnVaults, inverseKeyParts, inverseLenderKey, isFailedCall, isStablecoinSymbol, isYearnV3, keysFromMaps, lenderApiOnly, lenderFamily, liquityCandidateTroveIds, liquityKeyParts, liquityLenderKey, llamaLendKeyParts, llamaLendLenderKey, mergeDeep, multicall3Abi, nanTo, needsLenderApproval, needsTokenApproval, noOpResult, normalizeToBytes, parseBalanceFetcherResult, parseMergedResult, parseMulticallRpcResponses, parseRawRpcBatchResponses, parseRawRpcResponses, parseTermMaxLtv, parseTokenBalanceResult, pct, positivePart, predictInverseEscrow, prepareLenderUserDataRpcCalls, prepareMergedMulticallParams, prepareMergedRpcCalls, prepareMulticallInputs, prepareTokenBalanceRpcCalls, priceGlvVaults, priceGmMarkets, probeAaveFeedTimestamps, pruneFeedStats, rankFindings, readVaultSharePrices, rejectOutliers as rejectPriceOutliers, resolveAdapter, resolveDerivation, resolveStCeloDepositGroup, resupplyKeyParts, resupplyLenderKey, riverKeyParts, riverLenderKey, selectAssetGroupPrices, shortDate, stampVaultClassification, supplyDescription, supplyFindings, supplyHeadline, tellerBpsToPercent, tellerImpliedLtv, tellerLenderKey, tellerPoolFromLenderKey, termLenderKey, termMaxApiBase, borrowNif as termMaxBorrowNif, curveApr as termMaxCurveApr, curveAprNumber as termMaxCurveAprNumber, daysToMaturity as termMaxDaysToMaturity, lendNif as termMaxLendNif, mintGtFeeRatio as termMaxMintGtFeeRatio, ratioToNumber as termMaxRatioToNumber, ratioToPercent as termMaxRatioToPercent, tickToAprNumber, tickToPrice, toDigest, toTermSheetInput, unflattenLenderData, updateFeedStats, usddIlkBytes32, usddKeyParts, usddLenderKey, validateTermSheet, validateTermSheets, validateUserData };