@1delta/margin-fetcher 5.0.63 → 5.0.65
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 +166 -4
- package/dist/index.js +1099 -172
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Chain } from '@1delta/chain-registry';
|
|
|
9
9
|
import { multicallRetryUniversal, getEvmClient, getEvmChain, getEvmClientUniversal } from '@1delta/providers';
|
|
10
10
|
import { LiquityTroveManagerAbi, LiquityActivePoolAbi, LiquityStabilityPoolAbi, LiquityPriceFeedAbi, LiquitySortedTrovesAbi, RiverTroveManagerAbi, RiverStabilityPoolAbi, TellerMarketRegistryAbi, TellerV2Abi, InverseMarketAbi, InverseOracleAbi, InverseDbrAbi, Erc20Abi, CoolerMonoAbi, CoolerLtvOracleAbi, LlamaLendControllerAbi, LlamaLendControllerV1Abi, LlamaLendControllerV2Abi, LlamaLendVaultAbi, LlamaLendAmmAbi, TwyneCollateralVaultAbi, MetaMorphoAbi, FluidDexResolverAbi, ExactlyPreviewerAbi, ExactlyAuditorAbi, LenderCommitmentGroupAbi, ResupplyRegistryAbi, ResupplyPairAbi, ResupplyUtilitiesAbi, ResupplyRewardHandlerAbi, ResupplyPairEmissionsAbi, ConvexPoolUtilAbi, FraxlendPairAbi, FraxlendLeverAbi, FrankencoinPositionAbi, FluidLendingResolverAbi, FluidVaultResolverAbi, FluidLiquidityResolverAbi, MoolahVaultAbi, UsddVatAbi, UsddJugAbi, UsddSpotAbi, MorphoLensAbi, AaveV4SpokeAbi, AaveV4OracleAbi, AaveV4HubAbi, DolomiteMarginAbi, GearboxMarketCompressorV310Abi, MorphoBlueAbi, MidnightAbi, TermRepoTokenAbi, TermRepoServicerAbi, TermRepoCollateralManagerAbi, LiquityTroveNFTAbi, LiquityCollSurplusPoolAbi, TellerCollateralManagerAbi, TermMaxViewerAbi, InverseEscrowAbi, CurvanceMarketManagerAbi, CurvanceCTokenAbi, GearboxCreditAccountCompressorV310Abi, TwyneVaultManagerAbi, TwyneCollateralVaultFactoryAbi, AaveV2V3Abi, TwyneATokenWrapperAbi, UsddCdpManagerAbi, UsddProxyRegistryAbi, CurvanceProtocolReaderAbi, CurvanceCentralRegistryAbi, TermPriceConsumerAbi, CurvanceOracleManagerAbi, TermMaxOracleAggregatorV2Abi } from '@1delta/abis';
|
|
11
11
|
export { MorphoLensAbi } from '@1delta/abis';
|
|
12
|
-
import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getLstAcceptedInputs, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, findSavingsWithdrawEntry, bandLtvCurve, InitMarginAddresses } from '@1delta/calldata-sdk';
|
|
12
|
+
import { prepareDebitDataMulticall, prepareLenderDebitMulticall, parseDebitDataResult, parseLenderDebitResult, getPermit2ContractAddress, getLstAcceptedInputs, getCompoundV3CometAddress as getCompoundV3CometAddress$1, getMorphoAddress, getAaveCollateralTokenAddress, getSiloHalfForUnderlying, findSavingsWithdrawEntry, bandLtvCurve, InitMarginAddresses, ignoresReceiver, buildLstWithdrawRequest, SAVINGS_RECEIVER_CAPABILITY } from '@1delta/calldata-sdk';
|
|
13
13
|
import { proxyNativeFetch } from '@1delta/proxy-fetch';
|
|
14
14
|
import { BALANCER_V2_FORKS, BALANCER_V3_FORKS, UNISWAP_V4_FORKS, isFlashLoanSourceExcluded, FLASH_LOAN_IDS } from '@1delta/dex-registry';
|
|
15
15
|
|
|
@@ -10951,9 +10951,9 @@ function applyPositionDelta(positions, targetMarketUid, depositsDeltaUSD, debtDe
|
|
|
10951
10951
|
}
|
|
10952
10952
|
|
|
10953
10953
|
// src/lending/margin/base/sumer/deposit.ts
|
|
10954
|
-
function computeSumerDepositDelta(
|
|
10954
|
+
function computeSumerDepositDelta(amount4, price2, targetMarketUid, balanceData2, positions, createNewSubAccount = false, apr, yieldParams) {
|
|
10955
10955
|
const base = createNewSubAccount ? EMPTY_BALANCE : balanceData2;
|
|
10956
|
-
const dollarAmount =
|
|
10956
|
+
const dollarAmount = amount4 * price2;
|
|
10957
10957
|
const updatedPositions = applyPositionDelta(
|
|
10958
10958
|
positions,
|
|
10959
10959
|
targetMarketUid,
|
|
@@ -11019,8 +11019,8 @@ function computeSumerDepositDelta(amount3, price2, targetMarketUid, balanceData2
|
|
|
11019
11019
|
}
|
|
11020
11020
|
|
|
11021
11021
|
// src/lending/margin/base/sumer/withdraw.ts
|
|
11022
|
-
function computeSumerWithdrawDelta(
|
|
11023
|
-
const dollarAmount =
|
|
11022
|
+
function computeSumerWithdrawDelta(amount4, price2, targetMarketUid, balanceData2, positions, apr, yieldParams) {
|
|
11023
|
+
const dollarAmount = amount4 * price2;
|
|
11024
11024
|
const updatedPositions = applyPositionDelta(
|
|
11025
11025
|
positions,
|
|
11026
11026
|
targetMarketUid,
|
|
@@ -11086,8 +11086,8 @@ function computeSumerWithdrawDelta(amount3, price2, targetMarketUid, balanceData
|
|
|
11086
11086
|
}
|
|
11087
11087
|
|
|
11088
11088
|
// src/lending/margin/base/sumer/borrow.ts
|
|
11089
|
-
function computeSumerBorrowDelta(
|
|
11090
|
-
const dollarAmount =
|
|
11089
|
+
function computeSumerBorrowDelta(amount4, price2, targetMarketUid, balanceData2, positions, apr, yieldParams, irMode) {
|
|
11090
|
+
const dollarAmount = amount4 * price2;
|
|
11091
11091
|
const mode = irMode ?? 2;
|
|
11092
11092
|
const updatedPositions = applyPositionDelta(
|
|
11093
11093
|
positions,
|
|
@@ -11157,8 +11157,8 @@ function computeSumerBorrowDelta(amount3, price2, targetMarketUid, balanceData2,
|
|
|
11157
11157
|
}
|
|
11158
11158
|
|
|
11159
11159
|
// src/lending/margin/base/sumer/repay.ts
|
|
11160
|
-
function computeSumerRepayDelta(
|
|
11161
|
-
const dollarAmount =
|
|
11160
|
+
function computeSumerRepayDelta(amount4, price2, targetMarketUid, balanceData2, positions, apr, yieldParams, irMode) {
|
|
11161
|
+
const dollarAmount = amount4 * price2;
|
|
11162
11162
|
const mode = irMode ?? 2;
|
|
11163
11163
|
const updatedPositions = applyPositionDelta(
|
|
11164
11164
|
positions,
|
|
@@ -16661,13 +16661,13 @@ var REPAIR_BACKOFF_JITTER_MS = 60;
|
|
|
16661
16661
|
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
16662
16662
|
var backoffForRound = (round) => REPAIR_BACKOFF_BASE_MS * 2 ** round + Math.random() * REPAIR_BACKOFF_JITTER_MS;
|
|
16663
16663
|
var endpointUrl = (client, rpcId) => client?.transport?.url ?? `rpc#${rpcId}`;
|
|
16664
|
-
var resolveEndpoint = (chainId,
|
|
16664
|
+
var resolveEndpoint = (chainId, getEvmClient19, startRpcId, tried, maxProbe = 12, timeoutMs) => {
|
|
16665
16665
|
let fallback = null;
|
|
16666
16666
|
for (let probe = 0; probe < maxProbe; probe++) {
|
|
16667
16667
|
const rpcId = startRpcId + probe;
|
|
16668
16668
|
let client;
|
|
16669
16669
|
try {
|
|
16670
|
-
client =
|
|
16670
|
+
client = getEvmClient19(chainId, rpcId, { timeoutMs });
|
|
16671
16671
|
} catch {
|
|
16672
16672
|
break;
|
|
16673
16673
|
}
|
|
@@ -16696,7 +16696,7 @@ var recordPermanentFailures = (slots, offset, collector) => {
|
|
|
16696
16696
|
if (slots[i].permanent) collector.add(offset + i);
|
|
16697
16697
|
}
|
|
16698
16698
|
};
|
|
16699
|
-
var repairFailedSlots = async (chainId, contracts, slots,
|
|
16699
|
+
var repairFailedSlots = async (chainId, contracts, slots, getEvmClient19, nextRpcId, batchSize, logs, rounds = MULTICALL_REPAIR_ROUNDS, options) => {
|
|
16700
16700
|
let searchFrom = nextRpcId;
|
|
16701
16701
|
for (let round = 0; round < rounds; round++) {
|
|
16702
16702
|
const failedIdx = [];
|
|
@@ -16706,7 +16706,7 @@ var repairFailedSlots = async (chainId, contracts, slots, getEvmClient18, nextRp
|
|
|
16706
16706
|
if (failedIdx.length === 0) return slots;
|
|
16707
16707
|
const endpoint = resolveEndpoint(
|
|
16708
16708
|
chainId,
|
|
16709
|
-
|
|
16709
|
+
getEvmClient19,
|
|
16710
16710
|
searchFrom,
|
|
16711
16711
|
options?.tried
|
|
16712
16712
|
);
|
|
@@ -16758,7 +16758,7 @@ var repairFailedSlots = async (chainId, contracts, slots, getEvmClient18, nextRp
|
|
|
16758
16758
|
}
|
|
16759
16759
|
return slots;
|
|
16760
16760
|
};
|
|
16761
|
-
var multicallShardedAbiArray = async (chainId, abi, calls,
|
|
16761
|
+
var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient19, poolSize, retries = maxRetries, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, logs = false, retryFailed = false, permanentFailures, options) => {
|
|
16762
16762
|
const abiIsArray = isArray(abi[0]);
|
|
16763
16763
|
const contracts = calls.map(({ address, name, params }, i) => ({
|
|
16764
16764
|
abi: abiIsArray ? abi?.[i] : abi,
|
|
@@ -16832,7 +16832,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolS
|
|
|
16832
16832
|
const attemptHedged = async (items, startRpcId, tried) => {
|
|
16833
16833
|
const primary = resolveEndpoint(
|
|
16834
16834
|
chainId,
|
|
16835
|
-
|
|
16835
|
+
getEvmClient19,
|
|
16836
16836
|
startRpcId,
|
|
16837
16837
|
tried,
|
|
16838
16838
|
12,
|
|
@@ -16856,7 +16856,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolS
|
|
|
16856
16856
|
clearTimeout(timer);
|
|
16857
16857
|
const alt = resolveEndpoint(
|
|
16858
16858
|
chainId,
|
|
16859
|
-
|
|
16859
|
+
getEvmClient19,
|
|
16860
16860
|
primary.rpcId + 1,
|
|
16861
16861
|
tried,
|
|
16862
16862
|
12,
|
|
@@ -16908,7 +16908,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolS
|
|
|
16908
16908
|
chainId,
|
|
16909
16909
|
batch.items,
|
|
16910
16910
|
slots,
|
|
16911
|
-
|
|
16911
|
+
getEvmClient19,
|
|
16912
16912
|
won.rpcId + 1,
|
|
16913
16913
|
requestBytes,
|
|
16914
16914
|
logs,
|
|
@@ -16930,7 +16930,7 @@ var multicallShardedAbiArray = async (chainId, abi, calls, getEvmClient18, poolS
|
|
|
16930
16930
|
const tried = /* @__PURE__ */ new Set();
|
|
16931
16931
|
const start = resolveEndpoint(
|
|
16932
16932
|
chainId,
|
|
16933
|
-
|
|
16933
|
+
getEvmClient19,
|
|
16934
16934
|
workerId,
|
|
16935
16935
|
void 0,
|
|
16936
16936
|
12,
|
|
@@ -29674,8 +29674,9 @@ var LENS_FAMILY = {
|
|
|
29674
29674
|
*/
|
|
29675
29675
|
RESUPPLY: 15
|
|
29676
29676
|
};
|
|
29677
|
+
var V6_WITHHELD = /* @__PURE__ */ new Set([LENS_FAMILY.AAVE_V4]);
|
|
29677
29678
|
var ALL_FAMILIES = new Set(
|
|
29678
|
-
Object.values(LENS_FAMILY)
|
|
29679
|
+
Object.values(LENS_FAMILY).filter((f) => !V6_WITHHELD.has(f))
|
|
29679
29680
|
);
|
|
29680
29681
|
var v6 = () => ({
|
|
29681
29682
|
address: POSITION_LENS_V6,
|
|
@@ -34270,25 +34271,25 @@ var getFluidUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
34270
34271
|
legRaw(leg, supplyRaw).toString(),
|
|
34271
34272
|
leg.decimals
|
|
34272
34273
|
);
|
|
34273
|
-
const
|
|
34274
|
+
const amount4 = Number(amountStr);
|
|
34274
34275
|
const e = entryFor(leg);
|
|
34275
34276
|
e.deposits = amountStr;
|
|
34276
|
-
e.depositsUSD =
|
|
34277
|
-
e.depositsUSDOracle =
|
|
34277
|
+
e.depositsUSD = amount4 * leg.displayPrice;
|
|
34278
|
+
e.depositsUSDOracle = amount4 * leg.oraclePrice;
|
|
34278
34279
|
e.collateralEnabled = supplyRaw > 0n;
|
|
34279
|
-
deposits24h +=
|
|
34280
|
+
deposits24h += amount4 * leg.priceHist;
|
|
34280
34281
|
}
|
|
34281
34282
|
for (const leg of debtLegs) {
|
|
34282
34283
|
const amountStr = parseRawAmount(
|
|
34283
34284
|
legRaw(leg, borrowRaw).toString(),
|
|
34284
34285
|
leg.decimals
|
|
34285
34286
|
);
|
|
34286
|
-
const
|
|
34287
|
+
const amount4 = Number(amountStr);
|
|
34287
34288
|
const e = entryFor(leg);
|
|
34288
34289
|
e.debt = amountStr;
|
|
34289
|
-
e.debtUSD =
|
|
34290
|
-
e.debtUSDOracle =
|
|
34291
|
-
debt24h +=
|
|
34290
|
+
e.debtUSD = amount4 * leg.displayPrice;
|
|
34291
|
+
e.debtUSDOracle = amount4 * leg.oraclePrice;
|
|
34292
|
+
debt24h += amount4 * leg.priceHist;
|
|
34292
34293
|
}
|
|
34293
34294
|
histData[nftId] = {
|
|
34294
34295
|
totalDeposits24h: deposits24h,
|
|
@@ -34541,10 +34542,10 @@ var getDolomiteUserDataConverter = (lender, chainId, account, metaMap) => {
|
|
|
34541
34542
|
const meta = metaMap?.[key3];
|
|
34542
34543
|
if (!meta) return;
|
|
34543
34544
|
const decimals = meta.asset?.decimals ?? 18;
|
|
34544
|
-
const
|
|
34545
|
+
const amount4 = parseRawAmount(wei.value, decimals);
|
|
34545
34546
|
const isSupply = wei.sign;
|
|
34546
|
-
const deposits = isSupply ?
|
|
34547
|
-
const debt = isSupply ? "0" :
|
|
34547
|
+
const deposits = isSupply ? amount4 : "0";
|
|
34548
|
+
const debt = isSupply ? "0" : amount4;
|
|
34548
34549
|
const debtPar = isSupply ? "0" : pars[k]?.value?.toString() ?? "0";
|
|
34549
34550
|
const price2 = getDisplayPrice(meta);
|
|
34550
34551
|
const oPrice = getOraclePrice(meta);
|
|
@@ -35977,11 +35978,11 @@ var big13 = (v) => {
|
|
|
35977
35978
|
};
|
|
35978
35979
|
function fraxlendToAmount(shares, totalAmount, totalShares, roundUp) {
|
|
35979
35980
|
if (totalShares === 0n) return shares;
|
|
35980
|
-
let
|
|
35981
|
-
if (roundUp && totalAmount > 0n &&
|
|
35982
|
-
|
|
35981
|
+
let amount4 = shares * totalAmount / totalShares;
|
|
35982
|
+
if (roundUp && totalAmount > 0n && amount4 * totalShares / totalAmount < shares) {
|
|
35983
|
+
amount4 = amount4 + 1n;
|
|
35983
35984
|
}
|
|
35984
|
-
return
|
|
35985
|
+
return amount4;
|
|
35985
35986
|
}
|
|
35986
35987
|
var getFraxlendUserDataConverter = (lender, chainId, account, meta) => {
|
|
35987
35988
|
const pairs = fraxlendPairsFor(lender, chainId);
|
|
@@ -41897,7 +41898,7 @@ function unflattenLenderData(pools) {
|
|
|
41897
41898
|
}
|
|
41898
41899
|
return result;
|
|
41899
41900
|
}
|
|
41900
|
-
var getLenderUserDataResult = async (chainId, queriesRaw,
|
|
41901
|
+
var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient19, allowFailure = true, batchSize = MULTICALL_DEFAULT_BATCH_SIZE, retries = 3, logs = false, concurrency = 1, permanentFailures, onEndpointFailure) => {
|
|
41901
41902
|
const queries = organizeUserQueries(queriesRaw);
|
|
41902
41903
|
const builtCalls = await Promise.all(
|
|
41903
41904
|
queries.map(async (query3) => {
|
|
@@ -41907,7 +41908,7 @@ var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient18, allowF
|
|
|
41907
41908
|
query3.lender,
|
|
41908
41909
|
query3.account,
|
|
41909
41910
|
query3.params,
|
|
41910
|
-
|
|
41911
|
+
getEvmClient19
|
|
41911
41912
|
);
|
|
41912
41913
|
return callData.map((call) => ({ call, abi: call.abi ?? abi }));
|
|
41913
41914
|
})
|
|
@@ -41917,7 +41918,7 @@ var getLenderUserDataResult = async (chainId, queriesRaw, getEvmClient18, allowF
|
|
|
41917
41918
|
chainId,
|
|
41918
41919
|
calls.map((call) => call.abi),
|
|
41919
41920
|
calls.map((call) => call.call),
|
|
41920
|
-
|
|
41921
|
+
getEvmClient19,
|
|
41921
41922
|
concurrency,
|
|
41922
41923
|
retries,
|
|
41923
41924
|
allowFailure,
|
|
@@ -42216,29 +42217,29 @@ async function getMergedUserData(chainId, balanceQueries, permissionParams, lend
|
|
|
42216
42217
|
});
|
|
42217
42218
|
return parseMergedResult(chainId, rawResults, prepared, lenderState);
|
|
42218
42219
|
}
|
|
42219
|
-
function toCompoundV2Shares(entry,
|
|
42220
|
+
function toCompoundV2Shares(entry, amount4) {
|
|
42220
42221
|
const raw = entry.params?.exchangeRateCurrent;
|
|
42221
|
-
if (!raw || raw === "0x") return
|
|
42222
|
+
if (!raw || raw === "0x") return amount4;
|
|
42222
42223
|
try {
|
|
42223
42224
|
const exRate = BigInt(raw);
|
|
42224
|
-
if (exRate === 0n) return
|
|
42225
|
-
return
|
|
42225
|
+
if (exRate === 0n) return amount4;
|
|
42226
|
+
return amount4 * 10n ** 18n / exRate * 1001n / 1000n;
|
|
42226
42227
|
} catch {
|
|
42227
|
-
return
|
|
42228
|
+
return amount4;
|
|
42228
42229
|
}
|
|
42229
42230
|
}
|
|
42230
|
-
function toSiloShares(entry,
|
|
42231
|
+
function toSiloShares(entry, amount4, chainId, lender, tokenAddress) {
|
|
42231
42232
|
const raw = entry.params?.collateralRate;
|
|
42232
|
-
if (!raw || raw === "0x") return
|
|
42233
|
+
if (!raw || raw === "0x") return amount4;
|
|
42233
42234
|
try {
|
|
42234
42235
|
const rate = BigInt(raw);
|
|
42235
|
-
if (rate === 0n) return
|
|
42236
|
+
if (rate === 0n) return amount4;
|
|
42236
42237
|
const half = getSiloHalfForUnderlying(chainId, lender, tokenAddress);
|
|
42237
|
-
if (!half) return
|
|
42238
|
+
if (!half) return amount4;
|
|
42238
42239
|
const oneUnit = BigInt(10) ** BigInt(half.decimals);
|
|
42239
|
-
return
|
|
42240
|
+
return amount4 * oneUnit / rate * 1001n / 1000n;
|
|
42240
42241
|
} catch {
|
|
42241
|
-
return
|
|
42242
|
+
return amount4;
|
|
42242
42243
|
}
|
|
42243
42244
|
}
|
|
42244
42245
|
function resolveDebitDataKey(chainId, lender, tokenAddress, cToken, isProtected) {
|
|
@@ -42274,7 +42275,7 @@ function resolveDebitDataKey(chainId, lender, tokenAddress, cToken, isProtected)
|
|
|
42274
42275
|
return tokenAddress.toLowerCase();
|
|
42275
42276
|
}
|
|
42276
42277
|
function needsLenderApproval(params) {
|
|
42277
|
-
const { lender, lenderDebitData, tokenAddress, amount:
|
|
42278
|
+
const { lender, lenderDebitData, tokenAddress, amount: amount4, chainId, cToken, isProtected } = params;
|
|
42278
42279
|
if (!lenderDebitData) return true;
|
|
42279
42280
|
if (isAaveV4Type(lender)) {
|
|
42280
42281
|
const key4 = (params.aaveV4Spoke ?? tokenAddress).toLowerCase();
|
|
@@ -42291,33 +42292,33 @@ function needsLenderApproval(params) {
|
|
|
42291
42292
|
const entry = lenderDebitData[key3];
|
|
42292
42293
|
if (!entry || entry.amount === void 0) return true;
|
|
42293
42294
|
if (isCompoundV2Type(lender) || isVenusType(lender)) {
|
|
42294
|
-
const requiredShares = toCompoundV2Shares(entry,
|
|
42295
|
+
const requiredShares = toCompoundV2Shares(entry, amount4);
|
|
42295
42296
|
return entry.amount < requiredShares;
|
|
42296
42297
|
}
|
|
42297
42298
|
if (isSiloV2Type(lender) || isSiloV3Type(lender)) {
|
|
42298
|
-
const requiredShares = toSiloShares(entry,
|
|
42299
|
+
const requiredShares = toSiloShares(entry, amount4, chainId, lender, tokenAddress);
|
|
42299
42300
|
return entry.amount < requiredShares;
|
|
42300
42301
|
}
|
|
42301
42302
|
if (isCompoundV3(lender)) {
|
|
42302
42303
|
return entry.amount === 0n;
|
|
42303
42304
|
}
|
|
42304
|
-
return entry.amount <
|
|
42305
|
+
return entry.amount < amount4;
|
|
42305
42306
|
}
|
|
42306
42307
|
function needsTokenApproval(params) {
|
|
42307
|
-
const { debitData, spender, amount:
|
|
42308
|
+
const { debitData, spender, amount: amount4, chainId, usePermit2 } = params;
|
|
42308
42309
|
if (!debitData) return true;
|
|
42309
42310
|
const spenderLower = spender.toLowerCase();
|
|
42310
42311
|
if (usePermit2) {
|
|
42311
42312
|
const p2 = debitData.permit2?.[spenderLower];
|
|
42312
|
-
return !p2 || p2.amount <
|
|
42313
|
+
return !p2 || p2.amount < amount4;
|
|
42313
42314
|
}
|
|
42314
42315
|
const permit2Address = getPermit2ContractAddress(chainId).toLowerCase();
|
|
42315
42316
|
if (spenderLower === permit2Address) {
|
|
42316
42317
|
const p2 = debitData.permit2?.[spenderLower];
|
|
42317
|
-
if (p2 && p2.amount >=
|
|
42318
|
+
if (p2 && p2.amount >= amount4) return false;
|
|
42318
42319
|
}
|
|
42319
42320
|
const allowance = debitData.allowances?.[spenderLower] ?? 0n;
|
|
42320
|
-
return allowance <
|
|
42321
|
+
return allowance < amount4;
|
|
42321
42322
|
}
|
|
42322
42323
|
var MORPHO_USER_SUBGRAPH_URLS = {
|
|
42323
42324
|
[Chain.SEI_NETWORK]: "https://api.goldsky.com/api/public/project_cmiergfbv4vma01vb642yaeam/subgraphs/morphoblue-sei/1.0.1/gn",
|
|
@@ -42824,10 +42825,10 @@ function fuseLenderData(userDataResult, summary) {
|
|
|
42824
42825
|
}
|
|
42825
42826
|
|
|
42826
42827
|
// src/lending/margin/base/standard/deposit.ts
|
|
42827
|
-
function computeDepositDelta(
|
|
42828
|
+
function computeDepositDelta(amount4, price2, balanceData2, config, modeId, createNewSubAccount = false, apr, yieldParams) {
|
|
42828
42829
|
const { borrowCollateralFactor, collateralFactor } = getAssetConfig(config, modeId);
|
|
42829
42830
|
const base = createNewSubAccount ? EMPTY_BALANCE : balanceData2;
|
|
42830
|
-
const dollarAmount =
|
|
42831
|
+
const dollarAmount = amount4 * price2;
|
|
42831
42832
|
const postTrade = {
|
|
42832
42833
|
...base,
|
|
42833
42834
|
borrowDiscountedCollateral: base.borrowDiscountedCollateral + borrowCollateralFactor * dollarAmount,
|
|
@@ -42874,13 +42875,13 @@ function computeDepositDelta(amount3, price2, balanceData2, config, modeId, crea
|
|
|
42874
42875
|
}
|
|
42875
42876
|
|
|
42876
42877
|
// src/lending/margin/base/deposit.ts
|
|
42877
|
-
function computeDepositDelta2(lender,
|
|
42878
|
+
function computeDepositDelta2(lender, amount4, price2, balanceData2, config, modeId, createNewSubAccount, apr, yieldParams, targetMarketUid, positions) {
|
|
42878
42879
|
if (isSumerType(lender)) {
|
|
42879
42880
|
if (!positions || targetMarketUid === void 0) {
|
|
42880
42881
|
throw new Error("Sumer operations require positions and targetMarketUid");
|
|
42881
42882
|
}
|
|
42882
42883
|
return computeSumerDepositDelta(
|
|
42883
|
-
|
|
42884
|
+
amount4,
|
|
42884
42885
|
price2,
|
|
42885
42886
|
targetMarketUid,
|
|
42886
42887
|
balanceData2,
|
|
@@ -42894,7 +42895,7 @@ function computeDepositDelta2(lender, amount3, price2, balanceData2, config, mod
|
|
|
42894
42895
|
throw new Error("Standard operations require config and modeId");
|
|
42895
42896
|
}
|
|
42896
42897
|
return computeDepositDelta(
|
|
42897
|
-
|
|
42898
|
+
amount4,
|
|
42898
42899
|
price2,
|
|
42899
42900
|
balanceData2,
|
|
42900
42901
|
config,
|
|
@@ -42906,9 +42907,9 @@ function computeDepositDelta2(lender, amount3, price2, balanceData2, config, mod
|
|
|
42906
42907
|
}
|
|
42907
42908
|
|
|
42908
42909
|
// src/lending/margin/base/standard/withdraw.ts
|
|
42909
|
-
function computeWithdrawDelta(
|
|
42910
|
+
function computeWithdrawDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams) {
|
|
42910
42911
|
const { borrowCollateralFactor, collateralFactor } = getAssetConfig(config, modeId);
|
|
42911
|
-
const dollarAmount =
|
|
42912
|
+
const dollarAmount = amount4 * price2;
|
|
42912
42913
|
const postTrade = {
|
|
42913
42914
|
...balanceData2,
|
|
42914
42915
|
borrowDiscountedCollateral: balanceData2.borrowDiscountedCollateral - borrowCollateralFactor * dollarAmount,
|
|
@@ -42955,13 +42956,13 @@ function computeWithdrawDelta(amount3, price2, balanceData2, config, modeId, apr
|
|
|
42955
42956
|
}
|
|
42956
42957
|
|
|
42957
42958
|
// src/lending/margin/base/withdraw.ts
|
|
42958
|
-
function computeWithdrawDelta2(lender,
|
|
42959
|
+
function computeWithdrawDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, targetMarketUid, positions) {
|
|
42959
42960
|
if (isSumerType(lender)) {
|
|
42960
42961
|
if (!positions || targetMarketUid === void 0) {
|
|
42961
42962
|
throw new Error("Sumer operations require positions and targetMarketUid");
|
|
42962
42963
|
}
|
|
42963
42964
|
return computeSumerWithdrawDelta(
|
|
42964
|
-
|
|
42965
|
+
amount4,
|
|
42965
42966
|
price2,
|
|
42966
42967
|
targetMarketUid,
|
|
42967
42968
|
balanceData2,
|
|
@@ -42974,7 +42975,7 @@ function computeWithdrawDelta2(lender, amount3, price2, balanceData2, config, mo
|
|
|
42974
42975
|
throw new Error("Standard operations require config and modeId");
|
|
42975
42976
|
}
|
|
42976
42977
|
return computeWithdrawDelta(
|
|
42977
|
-
|
|
42978
|
+
amount4,
|
|
42978
42979
|
price2,
|
|
42979
42980
|
balanceData2,
|
|
42980
42981
|
config,
|
|
@@ -42985,9 +42986,9 @@ function computeWithdrawDelta2(lender, amount3, price2, balanceData2, config, mo
|
|
|
42985
42986
|
}
|
|
42986
42987
|
|
|
42987
42988
|
// src/lending/margin/base/standard/borrow.ts
|
|
42988
|
-
function computeBorrowDelta(
|
|
42989
|
+
function computeBorrowDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode) {
|
|
42989
42990
|
const { borrowFactor } = getAssetConfig(config, modeId);
|
|
42990
|
-
const dollarAmount =
|
|
42991
|
+
const dollarAmount = amount4 * price2;
|
|
42991
42992
|
const postTrade = {
|
|
42992
42993
|
...balanceData2,
|
|
42993
42994
|
debt: balanceData2.debt + dollarAmount,
|
|
@@ -43036,13 +43037,13 @@ function computeBorrowDelta(amount3, price2, balanceData2, config, modeId, apr,
|
|
|
43036
43037
|
}
|
|
43037
43038
|
|
|
43038
43039
|
// src/lending/margin/base/borrow.ts
|
|
43039
|
-
function computeBorrowDelta2(lender,
|
|
43040
|
+
function computeBorrowDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode, targetMarketUid, positions) {
|
|
43040
43041
|
if (isSumerType(lender)) {
|
|
43041
43042
|
if (!positions || targetMarketUid === void 0) {
|
|
43042
43043
|
throw new Error("Sumer operations require positions and targetMarketUid");
|
|
43043
43044
|
}
|
|
43044
43045
|
return computeSumerBorrowDelta(
|
|
43045
|
-
|
|
43046
|
+
amount4,
|
|
43046
43047
|
price2,
|
|
43047
43048
|
targetMarketUid,
|
|
43048
43049
|
balanceData2,
|
|
@@ -43056,7 +43057,7 @@ function computeBorrowDelta2(lender, amount3, price2, balanceData2, config, mode
|
|
|
43056
43057
|
throw new Error("Standard operations require config and modeId");
|
|
43057
43058
|
}
|
|
43058
43059
|
return computeBorrowDelta(
|
|
43059
|
-
|
|
43060
|
+
amount4,
|
|
43060
43061
|
price2,
|
|
43061
43062
|
balanceData2,
|
|
43062
43063
|
config,
|
|
@@ -43068,9 +43069,9 @@ function computeBorrowDelta2(lender, amount3, price2, balanceData2, config, mode
|
|
|
43068
43069
|
}
|
|
43069
43070
|
|
|
43070
43071
|
// src/lending/margin/base/standard/repay.ts
|
|
43071
|
-
function computeRepayDelta(
|
|
43072
|
+
function computeRepayDelta(amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode) {
|
|
43072
43073
|
const { borrowFactor } = getAssetConfig(config, modeId);
|
|
43073
|
-
const dollarAmount =
|
|
43074
|
+
const dollarAmount = amount4 * price2;
|
|
43074
43075
|
const postTrade = {
|
|
43075
43076
|
...balanceData2,
|
|
43076
43077
|
debt: balanceData2.debt - dollarAmount,
|
|
@@ -43119,13 +43120,13 @@ function computeRepayDelta(amount3, price2, balanceData2, config, modeId, apr, y
|
|
|
43119
43120
|
}
|
|
43120
43121
|
|
|
43121
43122
|
// src/lending/margin/base/repay.ts
|
|
43122
|
-
function computeRepayDelta2(lender,
|
|
43123
|
+
function computeRepayDelta2(lender, amount4, price2, balanceData2, config, modeId, apr, yieldParams, irMode, targetMarketUid, positions) {
|
|
43123
43124
|
if (isSumerType(lender)) {
|
|
43124
43125
|
if (!positions || targetMarketUid === void 0) {
|
|
43125
43126
|
throw new Error("Sumer operations require positions and targetMarketUid");
|
|
43126
43127
|
}
|
|
43127
43128
|
return computeSumerRepayDelta(
|
|
43128
|
-
|
|
43129
|
+
amount4,
|
|
43129
43130
|
price2,
|
|
43130
43131
|
targetMarketUid,
|
|
43131
43132
|
balanceData2,
|
|
@@ -43139,7 +43140,7 @@ function computeRepayDelta2(lender, amount3, price2, balanceData2, config, modeI
|
|
|
43139
43140
|
throw new Error("Standard operations require config and modeId");
|
|
43140
43141
|
}
|
|
43141
43142
|
return computeRepayDelta(
|
|
43142
|
-
|
|
43143
|
+
amount4,
|
|
43143
43144
|
price2,
|
|
43144
43145
|
balanceData2,
|
|
43145
43146
|
config,
|
|
@@ -45056,6 +45057,42 @@ var wbethFetcher = {
|
|
|
45056
45057
|
}
|
|
45057
45058
|
};
|
|
45058
45059
|
|
|
45060
|
+
// src/yields/intrinsic/fetchers/treehouse.ts
|
|
45061
|
+
var TETH_POOL_ID = "5762f4a8-bb48-45d6-90ed-2d93d1777169";
|
|
45062
|
+
var TAVAX_POOL_ID = "40a1e447-058d-4c5b-b567-30543ea185c3";
|
|
45063
|
+
var TREEHOUSE_APY_URL = "https://api.treehouse.finance/apy";
|
|
45064
|
+
var TETH_KEYS = ["Treehouse ETH::TETH", "Treehouse ETH::tETH"];
|
|
45065
|
+
var fetchTethApr = async () => {
|
|
45066
|
+
try {
|
|
45067
|
+
const res = await fetch(TREEHOUSE_APY_URL, {
|
|
45068
|
+
headers: { accept: "application/json" },
|
|
45069
|
+
signal: AbortSignal.timeout(8e3)
|
|
45070
|
+
});
|
|
45071
|
+
if (!res.ok) throw new Error(`Treehouse HTTP ${res.status}`);
|
|
45072
|
+
const json = await res.json();
|
|
45073
|
+
const apr = json?.total_apr_teth;
|
|
45074
|
+
if (typeof apr === "number" && Number.isFinite(apr) && apr > 0) return apr;
|
|
45075
|
+
throw new Error("Treehouse: no total_apr_teth");
|
|
45076
|
+
} catch {
|
|
45077
|
+
return apyToAprPercent(await fetchDefiLlamaApy(TETH_POOL_ID));
|
|
45078
|
+
}
|
|
45079
|
+
};
|
|
45080
|
+
var tethFetcher = {
|
|
45081
|
+
label: "TETH",
|
|
45082
|
+
fetch: async () => {
|
|
45083
|
+
const apr = await fetchTethApr();
|
|
45084
|
+
return Object.fromEntries(TETH_KEYS.map((k) => [k, apr]));
|
|
45085
|
+
}
|
|
45086
|
+
};
|
|
45087
|
+
var tavaxFetcher = {
|
|
45088
|
+
label: "TAVAX",
|
|
45089
|
+
fetch: async () => ({
|
|
45090
|
+
"Treehouse AVAX::tAVAX": apyToAprPercent(
|
|
45091
|
+
await fetchDefiLlamaApy(TAVAX_POOL_ID)
|
|
45092
|
+
)
|
|
45093
|
+
})
|
|
45094
|
+
};
|
|
45095
|
+
|
|
45059
45096
|
// src/vaults/lst/registry.ts
|
|
45060
45097
|
var LST_REGISTRY = {
|
|
45061
45098
|
// Monad (143) — native-MON LSTs. shMON / aprMON are ERC-4626 over native
|
|
@@ -45144,6 +45181,50 @@ var LST_REGISTRY = {
|
|
|
45144
45181
|
}
|
|
45145
45182
|
],
|
|
45146
45183
|
"1": [
|
|
45184
|
+
{
|
|
45185
|
+
// Treehouse tETH — an ERC-4626 share over wstETH that runs a
|
|
45186
|
+
// leveraged staking carry (wstETH collateral on Aave Core / Aave
|
|
45187
|
+
// Prime / Spark, ETH borrowed against it, converted back to wstETH).
|
|
45188
|
+
//
|
|
45189
|
+
// THREE things the generic 4626 path gets wrong here:
|
|
45190
|
+
// 1. `asset()` is NOT wstETH — it returns
|
|
45191
|
+
// `InternalAccountingUnit_Wrapped liquid staked Ether 2.0`
|
|
45192
|
+
// (`IAU_wstETH`, 0x1b6238e9…), a synthetic unit minted 1:1
|
|
45193
|
+
// against the real underlying. The underlying below is
|
|
45194
|
+
// `Vault.getUnderlying()`; never read `asset()`.
|
|
45195
|
+
// 2. Entry is the `TreehouseRouter`, not the share token. It takes
|
|
45196
|
+
// native ETH (`depositETH()`) or any `Vault.isAllowableAsset`
|
|
45197
|
+
// ERC-20 (stETH / WETH / wstETH) via `deposit(asset, amount)`,
|
|
45198
|
+
// and **credits `msg.sender`** — there is no receiver argument.
|
|
45199
|
+
// 3. Exit is neither of the share's own 4626 legs: `maxWithdraw`
|
|
45200
|
+
// and `maxRedeem` both read 0. It is the Fastlane (instant,
|
|
45201
|
+
// 50 bps) or RedemptionV2 (queued, 5 bps) — hence
|
|
45202
|
+
// `fee-or-queued`, with `liquidity` measured by the reader off
|
|
45203
|
+
// `Fastlane.getRedeemableAmount()`.
|
|
45204
|
+
address: "0xd11c452fc99cf405034ee446803b6f6c1f6d5ed8",
|
|
45205
|
+
underlying: "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0",
|
|
45206
|
+
// wstETH
|
|
45207
|
+
symbol: "tETH",
|
|
45208
|
+
brand: "Treehouse",
|
|
45209
|
+
decimals: 18,
|
|
45210
|
+
reader: "treehouseTAsset",
|
|
45211
|
+
isErc4626: true,
|
|
45212
|
+
isRebasing: false,
|
|
45213
|
+
isMintable: true,
|
|
45214
|
+
isNativeUnderlying: true,
|
|
45215
|
+
mintContract: "0xefa3fa8e85d2b3cfdb250cdea156c2c6c90628f5",
|
|
45216
|
+
// TreehouseRouter
|
|
45217
|
+
mintInputAsset: "native",
|
|
45218
|
+
withdrawalMode: "fee-or-queued",
|
|
45219
|
+
// Read live by the reader (7 d today, and it is an owner dial).
|
|
45220
|
+
withdrawalCooldownSeconds: 7 * 86400,
|
|
45221
|
+
yieldFetcher: tethFetcher,
|
|
45222
|
+
yieldKey: "Treehouse ETH::TETH",
|
|
45223
|
+
readerExtras: {
|
|
45224
|
+
treehouseFastlane: "0x829525417cd78cba0f99a8736426fc299506c0d6",
|
|
45225
|
+
treehouseRedemption: "0xcd63a29faff07130d3af89bb4f40778938aabb85"
|
|
45226
|
+
}
|
|
45227
|
+
},
|
|
45147
45228
|
{
|
|
45148
45229
|
address: "0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0",
|
|
45149
45230
|
underlying: "0x0000000000000000000000000000000000000000",
|
|
@@ -45295,8 +45376,14 @@ var LST_REGISTRY = {
|
|
|
45295
45376
|
yieldKey: "Restaked Swell ETH::RSWETH"
|
|
45296
45377
|
},
|
|
45297
45378
|
{
|
|
45379
|
+
// Puffer pufETH. The underlying is **WETH**, not wstETH: `asset()`
|
|
45380
|
+
// returns `0xC02aaA39…` and the vault holds ZERO wstETH (verified
|
|
45381
|
+
// on-chain 2026-08-25). It was wstETH-denominated at launch and the
|
|
45382
|
+
// registry never followed the migration, so the row valued 24,108 ETH
|
|
45383
|
+
// of assets at the wstETH price — a ~20 % TVL overstatement, and a
|
|
45384
|
+
// `convertToAssets` of 1.082 labelled in the wrong unit.
|
|
45298
45385
|
address: "0xd9a442856c234a39a81a089c06451ebaa4306a72",
|
|
45299
|
-
underlying: "
|
|
45386
|
+
underlying: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
45300
45387
|
symbol: "pufETH",
|
|
45301
45388
|
brand: "Puffer",
|
|
45302
45389
|
decimals: 18,
|
|
@@ -45306,7 +45393,8 @@ var LST_REGISTRY = {
|
|
|
45306
45393
|
isMintable: true,
|
|
45307
45394
|
isNativeUnderlying: true,
|
|
45308
45395
|
mintContract: "0xd9a442856c234a39a81a089c06451ebaa4306a72",
|
|
45309
|
-
|
|
45396
|
+
// The builder's only path is the native `depositETH(receiver)` zap.
|
|
45397
|
+
mintInputAsset: "native",
|
|
45310
45398
|
withdrawalMode: "fee-or-queued",
|
|
45311
45399
|
yieldFetcher: pufethFetcher,
|
|
45312
45400
|
yieldKey: "PUFETH"
|
|
@@ -45816,6 +45904,38 @@ var LST_REGISTRY = {
|
|
|
45816
45904
|
}
|
|
45817
45905
|
],
|
|
45818
45906
|
"43114": [
|
|
45907
|
+
{
|
|
45908
|
+
// Treehouse tAVAX — the tETH design on Avalanche, denominated in
|
|
45909
|
+
// BENQI sAVAX. Same Router / Vault / RedemptionController stack; see
|
|
45910
|
+
// the tETH entry on chain 1 for the three traps.
|
|
45911
|
+
//
|
|
45912
|
+
// The Avalanche Router carries NO `depositETH()` (selector-scanned
|
|
45913
|
+
// against the live runtime), so native AVAX is not an entry here —
|
|
45914
|
+
// the allowable set is sAVAX and WAVAX only.
|
|
45915
|
+
address: "0x14a84f1a61ccd7d1be596a6cc11fe33a36bc1646",
|
|
45916
|
+
underlying: "0x2b2c81e08f1af8835a78bb2a90ae924ace0ea4be",
|
|
45917
|
+
// sAVAX
|
|
45918
|
+
symbol: "tAVAX",
|
|
45919
|
+
brand: "Treehouse",
|
|
45920
|
+
decimals: 18,
|
|
45921
|
+
reader: "treehouseTAsset",
|
|
45922
|
+
isErc4626: true,
|
|
45923
|
+
isRebasing: false,
|
|
45924
|
+
isMintable: true,
|
|
45925
|
+
isNativeUnderlying: false,
|
|
45926
|
+
mintContract: "0x5f4d2e6c118b5e3c74f0b61de40f627ca9873d6e",
|
|
45927
|
+
// TreehouseRouter
|
|
45928
|
+
mintInputAsset: "0x2b2c81e08f1af8835a78bb2a90ae924ace0ea4be",
|
|
45929
|
+
withdrawalMode: "fee-or-queued",
|
|
45930
|
+
// 17 d live — NOT the 7 d the docs describe. Read live by the reader.
|
|
45931
|
+
withdrawalCooldownSeconds: 17 * 86400,
|
|
45932
|
+
yieldFetcher: tavaxFetcher,
|
|
45933
|
+
yieldKey: "Treehouse AVAX::tAVAX",
|
|
45934
|
+
readerExtras: {
|
|
45935
|
+
treehouseFastlane: "0x3d00a639183b07e35efef044ee6cc14e8598a01c",
|
|
45936
|
+
treehouseRedemption: "0x765f6dc8496ca7ef1e4a391be10185229aacf04b"
|
|
45937
|
+
}
|
|
45938
|
+
},
|
|
45819
45939
|
{
|
|
45820
45940
|
address: "0x2b2c81e08f1af8835a78bb2a90ae924ace0ea4be",
|
|
45821
45941
|
underlying: "0x0000000000000000000000000000000000000000",
|
|
@@ -45857,6 +45977,40 @@ var LST_REGISTRY = {
|
|
|
45857
45977
|
}
|
|
45858
45978
|
],
|
|
45859
45979
|
"999": [
|
|
45980
|
+
{
|
|
45981
|
+
// Treehouse tHYPE — the tETH design on HyperEVM, denominated in
|
|
45982
|
+
// Kinetiq kHYPE. Same stack; see the tETH entry on chain 1.
|
|
45983
|
+
//
|
|
45984
|
+
// No `depositETH()` on this Router either (selector-scanned), so the
|
|
45985
|
+
// entry set is kHYPE and WHYPE (0x5555…), never native HYPE.
|
|
45986
|
+
//
|
|
45987
|
+
// NO yield fetcher: DefiLlama carries no `treehouse-protocol` pool
|
|
45988
|
+
// for tHYPE and Treehouse's own `/apy` route serves tETH only, so the
|
|
45989
|
+
// row reports a `supplyRate` of 0 rather than an invented number.
|
|
45990
|
+
// The vault launched recently (share price 1.0007) — revisit with an
|
|
45991
|
+
// archival `convertToAssets` delta once it has real history.
|
|
45992
|
+
address: "0xb83d27f0f4133a7b0377a88089583131a903fdc7",
|
|
45993
|
+
underlying: "0xfd739d4e423301ce9385c1fb8850539d657c296d",
|
|
45994
|
+
// kHYPE
|
|
45995
|
+
symbol: "tHYPE",
|
|
45996
|
+
brand: "Treehouse",
|
|
45997
|
+
decimals: 18,
|
|
45998
|
+
reader: "treehouseTAsset",
|
|
45999
|
+
isErc4626: true,
|
|
46000
|
+
isRebasing: false,
|
|
46001
|
+
isMintable: true,
|
|
46002
|
+
isNativeUnderlying: false,
|
|
46003
|
+
mintContract: "0x1620b7e5c9099c8bcbc326b55e0b8440eda9d30a",
|
|
46004
|
+
// TreehouseRouter
|
|
46005
|
+
mintInputAsset: "0xfd739d4e423301ce9385c1fb8850539d657c296d",
|
|
46006
|
+
withdrawalMode: "fee-or-queued",
|
|
46007
|
+
// 10 d live — again not the docs' 7 d. Read live by the reader.
|
|
46008
|
+
withdrawalCooldownSeconds: 10 * 86400,
|
|
46009
|
+
readerExtras: {
|
|
46010
|
+
treehouseFastlane: "0x3018e0747549835faa8d06cf4809b1a2519fab31",
|
|
46011
|
+
treehouseRedemption: "0xcebbb011c2f29b0ed25895c54662bd1ccad30280"
|
|
46012
|
+
}
|
|
46013
|
+
},
|
|
45860
46014
|
{
|
|
45861
46015
|
// hbHYPE Ultra — Hyperbeat's ERC-4626 staked HYPE vault.
|
|
45862
46016
|
// TokenizedAccount impl, 4626-compliant, accepts WHYPE.
|
|
@@ -47525,6 +47679,86 @@ var strataFetcher = {
|
|
|
47525
47679
|
return out;
|
|
47526
47680
|
}
|
|
47527
47681
|
};
|
|
47682
|
+
var thBill = "Theo Short Duration US Treasury Fund::THBILL";
|
|
47683
|
+
var thBillBare = "thBILL::thBILL";
|
|
47684
|
+
var THBILL_DEFILLAMA_POOL = "e17dab50-85b1-45e8-b4a5-b8ae7898c4a3";
|
|
47685
|
+
var thbillFetcher = {
|
|
47686
|
+
label: "THBILL",
|
|
47687
|
+
fetch: async () => {
|
|
47688
|
+
const apy = await fetchDefiLlamaApy(THBILL_DEFILLAMA_POOL);
|
|
47689
|
+
const apr = apyToAprPercent(apy);
|
|
47690
|
+
return { [thBill]: apr, [thBillBare]: apr };
|
|
47691
|
+
}
|
|
47692
|
+
};
|
|
47693
|
+
var STHUSD_VAULT = "0xa808bc9775cb41c52c7842f8b50427fe7a770326";
|
|
47694
|
+
var STHUSD_UNIT = 10n ** 6n;
|
|
47695
|
+
var STHUSD_WINDOW_SECONDS = 30 * 24 * 60 * 60;
|
|
47696
|
+
var ETH_BLOCK_TIME_SECONDS = 12;
|
|
47697
|
+
var STHUSD_WINDOW_BLOCKS = BigInt(
|
|
47698
|
+
Math.floor(STHUSD_WINDOW_SECONDS / ETH_BLOCK_TIME_SECONDS)
|
|
47699
|
+
);
|
|
47700
|
+
var STHUSD_MAX_RPC_TRIES = 2;
|
|
47701
|
+
var STHUSD_DEADLINE_MS = 12e3;
|
|
47702
|
+
var STHUSD_KEY = "STHUSD";
|
|
47703
|
+
var STHUSD_GROUP_KEY = "Staked thUSD::STHUSD";
|
|
47704
|
+
var STHUSD_GROUP_KEY_OFT = "sthUSD::sthUSD";
|
|
47705
|
+
var CONVERT_TO_ASSETS_ABI4 = [
|
|
47706
|
+
{
|
|
47707
|
+
name: "convertToAssets",
|
|
47708
|
+
type: "function",
|
|
47709
|
+
stateMutability: "view",
|
|
47710
|
+
inputs: [{ type: "uint256" }],
|
|
47711
|
+
outputs: [{ type: "uint256" }]
|
|
47712
|
+
}
|
|
47713
|
+
];
|
|
47714
|
+
var readSthUsdRateAt = (client, blockNumber) => client.readContract({
|
|
47715
|
+
address: STHUSD_VAULT,
|
|
47716
|
+
abi: CONVERT_TO_ASSETS_ABI4,
|
|
47717
|
+
functionName: "convertToAssets",
|
|
47718
|
+
args: [STHUSD_UNIT],
|
|
47719
|
+
...blockNumber !== void 0 ? { blockNumber } : {}
|
|
47720
|
+
});
|
|
47721
|
+
var computeSthUsdApr = async () => {
|
|
47722
|
+
let lastErr;
|
|
47723
|
+
const deadline = Date.now() + STHUSD_DEADLINE_MS;
|
|
47724
|
+
for (let rpcId = 0; rpcId < STHUSD_MAX_RPC_TRIES; rpcId++) {
|
|
47725
|
+
if (Date.now() > deadline) break;
|
|
47726
|
+
try {
|
|
47727
|
+
const client = getEvmClient("1", rpcId);
|
|
47728
|
+
const head = await client.getBlockNumber();
|
|
47729
|
+
const pastBlock = head > STHUSD_WINDOW_BLOCKS ? head - STHUSD_WINDOW_BLOCKS : 0n;
|
|
47730
|
+
const [rateNow, rateThen, headBlock, thenBlock] = await Promise.all([
|
|
47731
|
+
readSthUsdRateAt(client),
|
|
47732
|
+
readSthUsdRateAt(client, pastBlock),
|
|
47733
|
+
client.getBlock({ blockNumber: head }),
|
|
47734
|
+
client.getBlock({ blockNumber: pastBlock })
|
|
47735
|
+
]);
|
|
47736
|
+
if (rateNow < STHUSD_UNIT || rateThen < STHUSD_UNIT) {
|
|
47737
|
+
throw new Error("sthUSD: share price below par \u2014 pruned or bad read");
|
|
47738
|
+
}
|
|
47739
|
+
if (rateNow < rateThen) {
|
|
47740
|
+
throw new Error("sthUSD: share price decreased \u2014 non-archival RPC");
|
|
47741
|
+
}
|
|
47742
|
+
const elapsed = Number(headBlock.timestamp - thenBlock.timestamp);
|
|
47743
|
+
if (elapsed <= 0) throw new Error("sthUSD: non-positive window");
|
|
47744
|
+
return annualizeRateDeltaPercent(rateNow, rateThen, elapsed);
|
|
47745
|
+
} catch (e) {
|
|
47746
|
+
lastErr = e;
|
|
47747
|
+
}
|
|
47748
|
+
}
|
|
47749
|
+
throw lastErr ?? new Error("sthUSD: no RPC served archive state");
|
|
47750
|
+
};
|
|
47751
|
+
var sthusdFetcher = {
|
|
47752
|
+
label: "STHUSD",
|
|
47753
|
+
fetch: async () => {
|
|
47754
|
+
const apr = await computeSthUsdApr().catch(() => 0);
|
|
47755
|
+
return {
|
|
47756
|
+
[STHUSD_KEY]: apr,
|
|
47757
|
+
[STHUSD_GROUP_KEY]: apr,
|
|
47758
|
+
[STHUSD_GROUP_KEY_OFT]: apr
|
|
47759
|
+
};
|
|
47760
|
+
}
|
|
47761
|
+
};
|
|
47528
47762
|
var RAY9 = 10n ** 27n;
|
|
47529
47763
|
var YEAR_SECONDS11 = 31536e3;
|
|
47530
47764
|
var DSR_ABI = [
|
|
@@ -50518,6 +50752,87 @@ var SINGLE_CHAIN_ENTRIES = {
|
|
|
50518
50752
|
solvency: "overcollateralized",
|
|
50519
50753
|
yieldFetcher: frankencoinSavingsFetcher,
|
|
50520
50754
|
yieldKey: zchfSavingsKey(Chain.ETHEREUM_MAINNET)
|
|
50755
|
+
},
|
|
50756
|
+
{
|
|
50757
|
+
// Theo **sthUSD** — the ERC-4626 staked wrapper over `thUSD`, Theo's
|
|
50758
|
+
// gold-yield stablecoin. Source Sourcify-verified on chain 1
|
|
50759
|
+
// (`contracts/thusd/SthUSD.sol` behind the UUPS proxy, impl
|
|
50760
|
+
// `0x342487f9…`), so every claim below is read off the code rather
|
|
50761
|
+
// than inferred.
|
|
50762
|
+
//
|
|
50763
|
+
// $24.20M held / 23.83M shares, price 1.015636 (2026-08-25). Ethereum
|
|
50764
|
+
// is the ONLY vault: `0xd1db2090…` is a LayerZero OFT Adapter that
|
|
50765
|
+
// LOCKS these shares and mints a bare OFT at the same address on
|
|
50766
|
+
// Stable (988), Arbitrum, BNB and Mantle — and **97 % of the supply
|
|
50767
|
+
// has left for Stable**, where the mirror is the largest Morpho Blue
|
|
50768
|
+
// collateral on the chain. See the `'988'` row for that side.
|
|
50769
|
+
//
|
|
50770
|
+
// **The yield is a PUSH, not a stream, and the row must not imply
|
|
50771
|
+
// otherwise.** A `yieldDistributor` calls `setYield(amount)`, which
|
|
50772
|
+
// reverts while `getUnvestedAmount() > 0`, so batches cannot overlap;
|
|
50773
|
+
// each vests over `vestingDuration` (10,800 s = 3 h) and then nothing
|
|
50774
|
+
// accrues until the next push. Measured daily on-chain, the share
|
|
50775
|
+
// price steps by at most +142e-6/day (≈ 5.10 % APR) with flat
|
|
50776
|
+
// stretches of up to nine days. `sthusdFetcher` reads a 30-day
|
|
50777
|
+
// trailing delta for exactly this reason — see its docstring before
|
|
50778
|
+
// reaching for a shorter window.
|
|
50779
|
+
//
|
|
50780
|
+
// **The exit is asynchronous and the wait is not free.**
|
|
50781
|
+
// `initiateRedeem(shares, owner)` is permissionless, but it BURNS the
|
|
50782
|
+
// shares immediately and snapshots `assets = convertToAssets(shares)`
|
|
50783
|
+
// at that block; the claim (`redeem`/`withdraw`) unlocks
|
|
50784
|
+
// `lockupPeriod` later and pays that frozen figure, so the five days
|
|
50785
|
+
// earn nothing and there is no cancel path. The claim additionally
|
|
50786
|
+
// requires `msg.sender == owner_` (`OwnerMustCompleteRedeem`), and
|
|
50787
|
+
// `initiateRedeem` books the request under the CALLER — so a
|
|
50788
|
+
// third-party redeem via allowance lands the request on the caller,
|
|
50789
|
+
// not the holder. Hence `request-based`, never `instant`.
|
|
50790
|
+
//
|
|
50791
|
+
// TRAP: **`previewRedeem` and `previewWithdraw` are hardcoded
|
|
50792
|
+
// `return 0`** — the protocol deprecated them in favour of
|
|
50793
|
+
// `maxWithdraw`/`maxRedeem`, which describe only a CLAIMABLE REQUEST
|
|
50794
|
+
// and so read 0 for every ordinary holder, including one sitting on
|
|
50795
|
+
// 23.2M shares for 27 days. Neither view can size an exit here, and
|
|
50796
|
+
// both are the obvious thing to reach for. `previewDeposit` is fine.
|
|
50797
|
+
//
|
|
50798
|
+
// `erc4626-cooldown` with `cooldownGetter: 'lockupPeriod'`: the pin
|
|
50799
|
+
// below is a snapshot of an `onlyOwner` dial with no timelock whose
|
|
50800
|
+
// `MAX_LOCKUP_PERIOD` is **30 days** — six times what is configured
|
|
50801
|
+
// today. Read it live, like Brix's.
|
|
50802
|
+
//
|
|
50803
|
+
// `nav-attested`, CURATED — the one field on this row that must not be
|
|
50804
|
+
// left to the builder's default. `totalAssets()` is honest about the
|
|
50805
|
+
// vault (its own thUSD balance, net of unvested yield and pending
|
|
50806
|
+
// redemptions), so the SHARES are backed by the asset; the trust
|
|
50807
|
+
// question sits one level down, in what backs thUSD — a gold-leasing
|
|
50808
|
+
// and CME-futures-roll book run off-chain and marked by the issuer,
|
|
50809
|
+
// with no on-chain solvency invariant anywhere. Absent, the builder
|
|
50810
|
+
// falls back to `overcollateralized` and only whispers the doubt
|
|
50811
|
+
// through `coverage.pending.counterparty`: a row that says
|
|
50812
|
+
// "overcollateralized" about attested gold is wrong in the one field a
|
|
50813
|
+
// reader checks before trusting the rate. Naming it also earns the
|
|
50814
|
+
// consequences — `nav-drawdown` in `principal.risks`, the
|
|
50815
|
+
// `nav-accrual` rate kind — which are all true here: the share price
|
|
50816
|
+
// moves only when a distributor chooses to push a batch. Same call as
|
|
50817
|
+
// Brix wiTRY.
|
|
50818
|
+
reader: "erc4626-cooldown",
|
|
50819
|
+
solvency: "nav-attested",
|
|
50820
|
+
cooldownGetter: "lockupPeriod",
|
|
50821
|
+
address: "0xa808bc9775cb41c52c7842f8b50427fe7a770326",
|
|
50822
|
+
underlying: "0xa3fe5c7596024e6811e14f029937d5bd8ae485b3",
|
|
50823
|
+
// thUSD
|
|
50824
|
+
symbol: "sthUSD",
|
|
50825
|
+
brand: "Theo",
|
|
50826
|
+
description: "thUSD is Theo's gold-yield stablecoin \u2014 the return comes from leasing physical gold and rolling CME futures, not from lending, and the book runs off-chain with no on-chain solvency invariant. sthUSD stakes it with an appreciating share price, but a distributor PUSHES each batch, so the price steps rather than streams and can sit flat for a week. Deposits are permissionless and uncapped. Exiting is a two-step request: initiating burns the shares and fixes the payout at that block's price, and the claim unlocks 5 days later \u2014 the wait earns nothing and cannot be cancelled.",
|
|
50827
|
+
decimals: 6,
|
|
50828
|
+
isRebasing: false,
|
|
50829
|
+
isMintable: true,
|
|
50830
|
+
withdrawalMode: "request-based",
|
|
50831
|
+
// `lockupPeriod()` = 432,000 s on 2026-08-25. Re-read live by the
|
|
50832
|
+
// reader; this is only the fallback if that call fails.
|
|
50833
|
+
withdrawalCooldownSeconds: 432e3,
|
|
50834
|
+
yieldFetcher: sthusdFetcher,
|
|
50835
|
+
yieldKey: STHUSD_KEY
|
|
50521
50836
|
}
|
|
50522
50837
|
],
|
|
50523
50838
|
"100": [
|
|
@@ -50743,6 +51058,70 @@ var SINGLE_CHAIN_ENTRIES = {
|
|
|
50743
51058
|
yieldKey: sparkVaultV2Key("43114", "spUSDC")
|
|
50744
51059
|
}
|
|
50745
51060
|
],
|
|
51061
|
+
// ---------------------------------------------------------------------
|
|
51062
|
+
// Stable (988) — a Tether-adjacent L1 whose whole lending surface is one
|
|
51063
|
+
// Morpho Blue deployment (`0xa40103…`), and whose largest market by an
|
|
51064
|
+
// order of magnitude is sthUSD/USDT0: $23.03M of collateral against
|
|
51065
|
+
// $18.59M supplied / $16.81M borrowed at 86 % LLTV. The earn row and that
|
|
51066
|
+
// collateral leg are the same asset, so registering it here is also what
|
|
51067
|
+
// gives the pair book a non-zero carry on the chain's biggest position.
|
|
51068
|
+
// ---------------------------------------------------------------------
|
|
51069
|
+
"988": [
|
|
51070
|
+
{
|
|
51071
|
+
// Theo **sthUSD**, bridged. This address is NOT the vault — it is the
|
|
51072
|
+
// LayerZero OFT minted against shares locked in the Ethereum OFT
|
|
51073
|
+
// Adapter at the same address, and it is a bare ERC-20 with a
|
|
51074
|
+
// blacklist and a pause: `asset()`, `totalAssets()`, `convertToAssets()`
|
|
51075
|
+
// and every `max*` view revert. See the chain-1 row for the vault,
|
|
51076
|
+
// its push-yield mechanism and its two-step exit.
|
|
51077
|
+
//
|
|
51078
|
+
// Priced by RedStone's **"RedStone Price Feed for sthUSD_FUNDAMENTAL"**
|
|
51079
|
+
// `0xb81131b6…` — the same feed Morpho's own oracle for this market
|
|
51080
|
+
// reads (`BASE_FEED_1` under a 1e28 `SCALE_FACTOR`), so the earn row
|
|
51081
|
+
// and the lending row cannot disagree about what a share is worth. It
|
|
51082
|
+
// is Chainlink-shaped and fresh, but answers in **8 decimals** (hence
|
|
51083
|
+
// `priceOracleDecimals`) and pins `roundId` at 1, i.e. NO round
|
|
51084
|
+
// history — an on-chain rate delta is impossible here, which is one
|
|
51085
|
+
// more reason `sthusdFetcher` measures the Ethereum vault instead.
|
|
51086
|
+
//
|
|
51087
|
+
// `underlying` is USDT0, the chain's dollar and this market's loan
|
|
51088
|
+
// asset: thUSD itself was never bridged to Stable, so there is no
|
|
51089
|
+
// local asset to name. Same call as Re's rows, which point at USDC.
|
|
51090
|
+
//
|
|
51091
|
+
// `isMintable: false` states a plain fact rather than a permission:
|
|
51092
|
+
// there is no mint function on an OFT and no vault on this chain, so
|
|
51093
|
+
// the only way in is to bridge from Ethereum. And it is deliberately
|
|
51094
|
+
// NOT `secondaryMarketOnly` — that flag promises a tradeable market,
|
|
51095
|
+
// and there isn't one: **23,216,009 of the 23,216,028 supply
|
|
51096
|
+
// (99.99997 %) sits inside Morpho Blue as collateral**, leaving ~19
|
|
51097
|
+
// sthUSD of free float across the whole chain. A `via: 'swap'` route
|
|
51098
|
+
// would advertise depth that does not exist.
|
|
51099
|
+
reader: "nav-oracle",
|
|
51100
|
+
// Same curated answer as the chain-1 row — one asset cannot have two
|
|
51101
|
+
// trust stories. Here it is doubly right: this side's price IS an
|
|
51102
|
+
// attestation, published by RedStone rather than derived from anything
|
|
51103
|
+
// the chain holds.
|
|
51104
|
+
solvency: "nav-attested",
|
|
51105
|
+
address: "0xd1db209087516883ec705cfeb99e80bb6032d540",
|
|
51106
|
+
underlying: "0x779ded0c9e1022225f8e0630b35a9b54be713736",
|
|
51107
|
+
// USDT0
|
|
51108
|
+
priceOracle: "0xb81131b6368b3f0a83af09db4e39ac23da96c2db",
|
|
51109
|
+
priceOracleDecimals: 8,
|
|
51110
|
+
symbol: "sthUSD",
|
|
51111
|
+
brand: "Theo",
|
|
51112
|
+
description: "Bridged sthUSD \u2014 Theo's staked gold-yield dollar, whose vault lives on Ethereum; this is the LayerZero token minted against shares locked there, priced by RedStone's sthUSD NAV feed. It holds 97 % of the supply and is the largest Morpho Blue collateral on Stable. There is no vault on this chain: entering and exiting both mean bridging to Ethereum, where redemption is a request that burns the shares at today's price and pays out 5 days later.",
|
|
51113
|
+
decimals: 6,
|
|
51114
|
+
underlyingDecimals: 6,
|
|
51115
|
+
isRebasing: false,
|
|
51116
|
+
isMintable: false,
|
|
51117
|
+
withdrawalMode: "request-based",
|
|
51118
|
+
// The Ethereum vault's `lockupPeriod`, plus a bridge hop each way that
|
|
51119
|
+
// this number does not include.
|
|
51120
|
+
withdrawalCooldownSeconds: 432e3,
|
|
51121
|
+
yieldFetcher: sthusdFetcher,
|
|
51122
|
+
yieldKey: STHUSD_KEY
|
|
51123
|
+
}
|
|
51124
|
+
],
|
|
50746
51125
|
"4663": [
|
|
50747
51126
|
{
|
|
50748
51127
|
// Spark Vaults V2 spUSDG on Robinhood Chain — the first V2 vault
|
|
@@ -50861,17 +51240,6 @@ var jitoSolFetcher = {
|
|
|
50861
51240
|
}
|
|
50862
51241
|
};
|
|
50863
51242
|
|
|
50864
|
-
// src/yields/intrinsic/fetchers/theo.ts
|
|
50865
|
-
var thBill = "Theo Short Duration US Treasury Fund::THBILL";
|
|
50866
|
-
var THBILL_DEFILLAMA_POOL = "e17dab50-85b1-45e8-b4a5-b8ae7898c4a3";
|
|
50867
|
-
var thbillFetcher = {
|
|
50868
|
-
label: "THBILL",
|
|
50869
|
-
fetch: async () => {
|
|
50870
|
-
const apy = await fetchDefiLlamaApy(THBILL_DEFILLAMA_POOL);
|
|
50871
|
-
return { [thBill]: apyToAprPercent(apy) };
|
|
50872
|
-
}
|
|
50873
|
-
};
|
|
50874
|
-
|
|
50875
51243
|
// src/yields/intrinsic/fetchers/superreturn.ts
|
|
50876
51244
|
var SSUPERUSD_URL = "https://www.superreturn.ai/api/trpc/cmc.getUSDCPrice,rewardBackend.getYield,rewardBackend.getTvlChange?batch=1&input=%7B%220%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%2C%221%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%2C%222%22%3A%7B%22json%22%3Anull%2C%22meta%22%3A%7B%22values%22%3A%5B%22undefined%22%5D%7D%7D%7D";
|
|
50877
51245
|
var ssuperusd = "SuperReturn sSuperUSD::SSUPERUSD";
|
|
@@ -51586,25 +51954,14 @@ var lsethFetcher = {
|
|
|
51586
51954
|
}
|
|
51587
51955
|
};
|
|
51588
51956
|
|
|
51589
|
-
// src/yields/intrinsic/fetchers/treehouse.ts
|
|
51590
|
-
var TETH_POOL_ID = "5762f4a8-bb48-45d6-90ed-2d93d1777169";
|
|
51591
|
-
var KEYS2 = ["Treehouse ETH::tETH"];
|
|
51592
|
-
var tethFetcher = {
|
|
51593
|
-
label: "TETH",
|
|
51594
|
-
fetch: async () => {
|
|
51595
|
-
const apr = apyToAprPercent(await fetchDefiLlamaApy(TETH_POOL_ID));
|
|
51596
|
-
return Object.fromEntries(KEYS2.map((k) => [k, apr]));
|
|
51597
|
-
}
|
|
51598
|
-
};
|
|
51599
|
-
|
|
51600
51957
|
// src/yields/intrinsic/fetchers/anzen.ts
|
|
51601
51958
|
var SUSDZ_POOL_ID = "46518e93-8197-4539-9861-2340c2ac965a";
|
|
51602
|
-
var
|
|
51959
|
+
var KEYS2 = ["Anzen Staked USDz::SUSDZ", "Anzen Staked USDz::sUSDz", "Staked USDz::sUSDz"];
|
|
51603
51960
|
var susdzFetcher = {
|
|
51604
51961
|
label: "SUSDZ",
|
|
51605
51962
|
fetch: async () => {
|
|
51606
51963
|
const apr = apyToAprPercent(await fetchDefiLlamaApy(SUSDZ_POOL_ID));
|
|
51607
|
-
return Object.fromEntries(
|
|
51964
|
+
return Object.fromEntries(KEYS2.map((k) => [k, apr]));
|
|
51608
51965
|
}
|
|
51609
51966
|
};
|
|
51610
51967
|
|
|
@@ -51617,6 +51974,7 @@ var LENDING_ONLY_FETCHERS = [
|
|
|
51617
51974
|
ethZeroFetcher,
|
|
51618
51975
|
jitoSolFetcher,
|
|
51619
51976
|
thbillFetcher,
|
|
51977
|
+
sthusdFetcher,
|
|
51620
51978
|
ssuperusdFetcher,
|
|
51621
51979
|
hlpFetcher,
|
|
51622
51980
|
hwhlpFetcher,
|
|
@@ -51631,7 +51989,10 @@ var LENDING_ONLY_FETCHERS = [
|
|
|
51631
51989
|
// it reaches the global map via `collectVaultFetchers` (disjointness rule).
|
|
51632
51990
|
syzusdFetcher,
|
|
51633
51991
|
midasFetcher,
|
|
51634
|
-
capFetcher,
|
|
51992
|
+
// capFetcher is NOT here: the Cap stcUSD savings row vault-wires it, so it
|
|
51993
|
+
// reaches the global map via `collectVaultFetchers` (disjointness rule).
|
|
51994
|
+
// It was double-listed, which the registry test flags — the union dedupes
|
|
51995
|
+
// by reference, so removing it here changes nothing at runtime.
|
|
51635
51996
|
nestFetcher,
|
|
51636
51997
|
accountableFetcher,
|
|
51637
51998
|
upshiftFetcher,
|
|
@@ -51640,7 +52001,9 @@ var LENDING_ONLY_FETCHERS = [
|
|
|
51640
52001
|
yearnFetcher,
|
|
51641
52002
|
// DefiLlama-mapped intrinsic yields for classifier assets lacking a bespoke source
|
|
51642
52003
|
lsethFetcher,
|
|
51643
|
-
tethFetcher
|
|
52004
|
+
// tethFetcher / tavaxFetcher are NOT here: the Treehouse tAsset LST rows
|
|
52005
|
+
// vault-wire them, so they reach the global map via `collectVaultFetchers`
|
|
52006
|
+
// (disjointness rule).
|
|
51644
52007
|
// strataFetcher is NOT here: the Strata tranche savings rows vault-wire
|
|
51645
52008
|
// it, so it reaches the global map via `collectVaultFetchers`.
|
|
51646
52009
|
susdzFetcher
|
|
@@ -53467,9 +53830,9 @@ function getTermCalls(chainId) {
|
|
|
53467
53830
|
}
|
|
53468
53831
|
}
|
|
53469
53832
|
const results = [];
|
|
53470
|
-
for (const [token, { amount:
|
|
53833
|
+
for (const [token, { amount: amount4, repoKeys }] of byToken) {
|
|
53471
53834
|
const calls = [
|
|
53472
|
-
{ address: oracle, name: "usdValueOfTokens", params: [token,
|
|
53835
|
+
{ address: oracle, name: "usdValueOfTokens", params: [token, amount4] }
|
|
53473
53836
|
];
|
|
53474
53837
|
results.push({
|
|
53475
53838
|
calls,
|
|
@@ -61680,6 +62043,165 @@ var readerKintsuSMon = (entry) => ({
|
|
|
61680
62043
|
}
|
|
61681
62044
|
});
|
|
61682
62045
|
|
|
62046
|
+
// src/vaults/lst/abis/treehouse.ts
|
|
62047
|
+
var TreehouseFastlaneAbi = [
|
|
62048
|
+
{
|
|
62049
|
+
name: "getRedeemableAmount",
|
|
62050
|
+
type: "function",
|
|
62051
|
+
stateMutability: "view",
|
|
62052
|
+
inputs: [],
|
|
62053
|
+
outputs: [{ type: "uint256" }]
|
|
62054
|
+
},
|
|
62055
|
+
{
|
|
62056
|
+
// Delegates to a swappable fee contract, so it is a live read even
|
|
62057
|
+
// though the Fastlane itself is behind the timelock.
|
|
62058
|
+
name: "redemptionFee",
|
|
62059
|
+
type: "function",
|
|
62060
|
+
stateMutability: "view",
|
|
62061
|
+
inputs: [],
|
|
62062
|
+
outputs: [{ type: "uint256" }]
|
|
62063
|
+
},
|
|
62064
|
+
{
|
|
62065
|
+
name: "minRedeemInUnderlying",
|
|
62066
|
+
type: "function",
|
|
62067
|
+
stateMutability: "view",
|
|
62068
|
+
inputs: [],
|
|
62069
|
+
outputs: [{ type: "uint96" }]
|
|
62070
|
+
}
|
|
62071
|
+
];
|
|
62072
|
+
var TreehouseRedemptionAbi = [
|
|
62073
|
+
{
|
|
62074
|
+
name: "waitingPeriod",
|
|
62075
|
+
type: "function",
|
|
62076
|
+
stateMutability: "view",
|
|
62077
|
+
inputs: [],
|
|
62078
|
+
outputs: [{ type: "uint32" }]
|
|
62079
|
+
},
|
|
62080
|
+
{
|
|
62081
|
+
// The QUEUED leg charges too (5 bps). That contradicts the convention
|
|
62082
|
+
// `SavingsVault.withdrawFeeBps` documents — "the queued leg pays at par"
|
|
62083
|
+
// — which is exactly why the route list carries a fee PER LEG instead of
|
|
62084
|
+
// one field plus an assumption.
|
|
62085
|
+
name: "redemptionFee",
|
|
62086
|
+
type: "function",
|
|
62087
|
+
stateMutability: "view",
|
|
62088
|
+
inputs: [],
|
|
62089
|
+
outputs: [{ type: "uint32" }]
|
|
62090
|
+
},
|
|
62091
|
+
{
|
|
62092
|
+
// The gate that decides whether the cheap leg exists for a given holder:
|
|
62093
|
+
// 50 wstETH / 4,000 sAVAX / 1,000 kHYPE, checked against
|
|
62094
|
+
// `previewRedeem(shares)`, i.e. in UNDERLYING units.
|
|
62095
|
+
name: "minRedeemInUnderlying",
|
|
62096
|
+
type: "function",
|
|
62097
|
+
stateMutability: "view",
|
|
62098
|
+
inputs: [],
|
|
62099
|
+
outputs: [{ type: "uint96" }]
|
|
62100
|
+
}
|
|
62101
|
+
];
|
|
62102
|
+
|
|
62103
|
+
// src/vaults/lst/readers/treehouse.ts
|
|
62104
|
+
var asBps = (v) => v === void 0 ? void 0 : Number(v);
|
|
62105
|
+
var fmt = (raw, decimals) => raw === void 0 ? void 0 : Number(raw) / 10 ** decimals;
|
|
62106
|
+
var readerTreehouseTAsset = (entry) => {
|
|
62107
|
+
const fastlane = entry.readerExtras?.treehouseFastlane;
|
|
62108
|
+
const redemption = entry.readerExtras?.treehouseRedemption;
|
|
62109
|
+
const fl = fastlane ?? entry.address;
|
|
62110
|
+
const rd = redemption ?? entry.address;
|
|
62111
|
+
const underlyingDec = entry.underlyingDecimals ?? entry.decimals;
|
|
62112
|
+
return {
|
|
62113
|
+
calls: [
|
|
62114
|
+
{ address: entry.address, name: "totalAssets", params: [] },
|
|
62115
|
+
{ address: entry.address, name: "totalSupply", params: [] },
|
|
62116
|
+
{ address: entry.address, name: "convertToAssets", params: [ONE_E1811] },
|
|
62117
|
+
{ address: fl, name: "getRedeemableAmount", params: [] },
|
|
62118
|
+
{ address: fl, name: "redemptionFee", params: [] },
|
|
62119
|
+
{ address: fl, name: "minRedeemInUnderlying", params: [] },
|
|
62120
|
+
{ address: rd, name: "waitingPeriod", params: [] },
|
|
62121
|
+
{ address: rd, name: "redemptionFee", params: [] },
|
|
62122
|
+
{ address: rd, name: "minRedeemInUnderlying", params: [] }
|
|
62123
|
+
],
|
|
62124
|
+
abis: [
|
|
62125
|
+
Erc4626ReadAbi,
|
|
62126
|
+
TotalSupplyAbi,
|
|
62127
|
+
Erc4626ReadAbi,
|
|
62128
|
+
TreehouseFastlaneAbi,
|
|
62129
|
+
TreehouseFastlaneAbi,
|
|
62130
|
+
TreehouseFastlaneAbi,
|
|
62131
|
+
TreehouseRedemptionAbi,
|
|
62132
|
+
TreehouseRedemptionAbi,
|
|
62133
|
+
TreehouseRedemptionAbi
|
|
62134
|
+
],
|
|
62135
|
+
parse: (slice2) => {
|
|
62136
|
+
const [
|
|
62137
|
+
assets,
|
|
62138
|
+
supply,
|
|
62139
|
+
rate,
|
|
62140
|
+
redeemable,
|
|
62141
|
+
fastFee,
|
|
62142
|
+
fastMin,
|
|
62143
|
+
waiting,
|
|
62144
|
+
queueFee,
|
|
62145
|
+
queueMin
|
|
62146
|
+
] = slice2;
|
|
62147
|
+
const totalAssets = toBigInt13(assets);
|
|
62148
|
+
const totalSupply = toBigInt13(supply);
|
|
62149
|
+
const exchangeRate = toBigInt13(rate);
|
|
62150
|
+
if (totalAssets === void 0 || totalSupply === void 0 || exchangeRate === void 0) {
|
|
62151
|
+
return void 0;
|
|
62152
|
+
}
|
|
62153
|
+
const liquidity = toBigInt13(redeemable) ?? 0n;
|
|
62154
|
+
const wait = toBigInt13(waiting);
|
|
62155
|
+
const instantFeeBps = asBps(toBigInt13(fastFee));
|
|
62156
|
+
const queuedFeeBps = asBps(toBigInt13(queueFee));
|
|
62157
|
+
const instantMin = toBigInt13(fastMin);
|
|
62158
|
+
const queuedMin = toBigInt13(queueMin);
|
|
62159
|
+
const instant = {
|
|
62160
|
+
id: "instant",
|
|
62161
|
+
kind: "instant",
|
|
62162
|
+
label: "Fast redemption",
|
|
62163
|
+
settlement: "sync",
|
|
62164
|
+
feeBps: instantFeeBps,
|
|
62165
|
+
waitSeconds: 0,
|
|
62166
|
+
// `0` is the live value on all three chains and means "no floor" —
|
|
62167
|
+
// emitted rather than dropped, because on this protocol the ABSENCE
|
|
62168
|
+
// of a minimum on the expensive leg is the reason it is the only exit
|
|
62169
|
+
// most holders have.
|
|
62170
|
+
minAmount: instantMin?.toString(),
|
|
62171
|
+
minAmountFormatted: fmt(instantMin, underlyingDec),
|
|
62172
|
+
capacity: liquidity.toString(),
|
|
62173
|
+
capacityFormatted: Number(liquidity) / 10 ** underlyingDec,
|
|
62174
|
+
selfOnly: true,
|
|
62175
|
+
description: "Burns the tAsset and pays the underlying in the same transaction, out of the vault balance not already earmarked by queued requests. Bounded by that balance \u2014 a larger redemption reverts rather than partially filling."
|
|
62176
|
+
};
|
|
62177
|
+
const queued = {
|
|
62178
|
+
id: "queued",
|
|
62179
|
+
kind: "queued",
|
|
62180
|
+
label: wait !== void 0 ? `${Math.round(Number(wait) / 86400)}-day queue` : "Queued redemption",
|
|
62181
|
+
settlement: "async",
|
|
62182
|
+
feeBps: queuedFeeBps,
|
|
62183
|
+
waitSeconds: wait !== void 0 ? Number(wait) : void 0,
|
|
62184
|
+
minAmount: queuedMin?.toString(),
|
|
62185
|
+
minAmountFormatted: fmt(queuedMin, underlyingDec),
|
|
62186
|
+
selfOnly: true,
|
|
62187
|
+
description: "Escrows the shares now and pays after the wait. Far cheaper, but it enforces a minimum size, and it settles at the WORSE of the rate at request and at claim \u2014 so the amount quoted when you file it is a ceiling, not a quote."
|
|
62188
|
+
};
|
|
62189
|
+
return {
|
|
62190
|
+
totalAssets,
|
|
62191
|
+
totalSupply,
|
|
62192
|
+
exchangeRate,
|
|
62193
|
+
liquidity,
|
|
62194
|
+
withdrawalCooldownSeconds: wait !== void 0 ? Number(wait) : void 0,
|
|
62195
|
+
withdrawFeeBps: instantFeeBps,
|
|
62196
|
+
// Cheapest reachable leg first is the list's ordering rule, and here
|
|
62197
|
+
// the cheap one is second on purpose: it is gated by a minimum that
|
|
62198
|
+
// most holders do not clear, so the leg anyone can take leads.
|
|
62199
|
+
exitRoutes: [instant, queued]
|
|
62200
|
+
};
|
|
62201
|
+
}
|
|
62202
|
+
};
|
|
62203
|
+
};
|
|
62204
|
+
|
|
61683
62205
|
// src/vaults/lst/readers/index.ts
|
|
61684
62206
|
var buildReader = (entry) => {
|
|
61685
62207
|
switch (entry.reader) {
|
|
@@ -61741,6 +62263,8 @@ var buildReader = (entry) => {
|
|
|
61741
62263
|
return readerCoreStakedRatio(entry);
|
|
61742
62264
|
case "kintsuSMon":
|
|
61743
62265
|
return readerKintsuSMon(entry);
|
|
62266
|
+
case "treehouseTAsset":
|
|
62267
|
+
return readerTreehouseTAsset(entry);
|
|
61744
62268
|
}
|
|
61745
62269
|
};
|
|
61746
62270
|
|
|
@@ -62110,6 +62634,98 @@ var getLstValidators = async (chainId, shareToken) => {
|
|
|
62110
62634
|
return [];
|
|
62111
62635
|
};
|
|
62112
62636
|
|
|
62637
|
+
// src/vaults/exitRoutes.ts
|
|
62638
|
+
var asyncLabel = (secs) => {
|
|
62639
|
+
if (!secs || secs <= 0) return "Queued";
|
|
62640
|
+
const d = secs / 86400;
|
|
62641
|
+
if (d >= 1) return `${Number.isInteger(d) ? d : d.toFixed(1)}-day queue`;
|
|
62642
|
+
const h = secs / 3600;
|
|
62643
|
+
return h >= 1 ? `${Number.isInteger(h) ? h : h.toFixed(1)}-hour queue` : `${Math.round(secs / 60)}-minute queue`;
|
|
62644
|
+
};
|
|
62645
|
+
var instantRoute = (i, feeBps) => ({
|
|
62646
|
+
id: "instant",
|
|
62647
|
+
kind: "instant",
|
|
62648
|
+
label: feeBps ? "Instant (fee)" : "Instant",
|
|
62649
|
+
settlement: "sync",
|
|
62650
|
+
feeBps,
|
|
62651
|
+
waitSeconds: 0,
|
|
62652
|
+
capacity: i.liquidity,
|
|
62653
|
+
capacityFormatted: i.liquidityFormatted,
|
|
62654
|
+
capacityUsd: i.liquidityUsd
|
|
62655
|
+
});
|
|
62656
|
+
var queuedRoute = (i) => ({
|
|
62657
|
+
id: "queued",
|
|
62658
|
+
kind: "queued",
|
|
62659
|
+
label: asyncLabel(i.withdrawalCooldownSeconds),
|
|
62660
|
+
settlement: "async",
|
|
62661
|
+
waitSeconds: i.withdrawalCooldownSeconds
|
|
62662
|
+
});
|
|
62663
|
+
var deriveExitRoutes = (i) => {
|
|
62664
|
+
switch (i.withdrawalMode) {
|
|
62665
|
+
// The instant leg pays the fee; the queue pays at par. That is the
|
|
62666
|
+
// convention `SavingsVault.withdrawFeeBps` already documents — and
|
|
62667
|
+
// Treehouse is the counter-example, which is why its reader overrides
|
|
62668
|
+
// this rather than being described by it.
|
|
62669
|
+
case "fee-or-queued":
|
|
62670
|
+
return [
|
|
62671
|
+
{
|
|
62672
|
+
...instantRoute(i, i.withdrawFeeBps),
|
|
62673
|
+
// The mode's whole meaning is that THIS leg costs something. Say so
|
|
62674
|
+
// even when the size is unknown: an absent `feeBps` renders as
|
|
62675
|
+
// "leave instantly", which reads as free — the same failure the
|
|
62676
|
+
// term-sheet rules call out for `fees: []`.
|
|
62677
|
+
...i.withdrawFeeBps == null ? { feeUnknown: true, label: "Instant (fee)" } : {}
|
|
62678
|
+
},
|
|
62679
|
+
{ ...queuedRoute(i), feeBps: 0 }
|
|
62680
|
+
];
|
|
62681
|
+
// Same split with no fee on either leg — the instant leg is bounded by
|
|
62682
|
+
// inventory instead.
|
|
62683
|
+
case "instant-or-queued":
|
|
62684
|
+
return [instantRoute(i, i.withdrawFeeBps ?? 0), queuedRoute(i)];
|
|
62685
|
+
case "instant":
|
|
62686
|
+
return [
|
|
62687
|
+
{
|
|
62688
|
+
id: "instant",
|
|
62689
|
+
kind: "instant",
|
|
62690
|
+
label: "Instant",
|
|
62691
|
+
settlement: "sync",
|
|
62692
|
+
feeBps: i.withdrawFeeBps ?? 0,
|
|
62693
|
+
waitSeconds: 0
|
|
62694
|
+
}
|
|
62695
|
+
];
|
|
62696
|
+
case "instant-capped":
|
|
62697
|
+
return [instantRoute(i, i.withdrawFeeBps ?? 0)];
|
|
62698
|
+
case "fixed-cooldown":
|
|
62699
|
+
case "queued":
|
|
62700
|
+
case "request-based":
|
|
62701
|
+
return [{ ...queuedRoute(i), feeBps: i.withdrawFeeBps }];
|
|
62702
|
+
case "off-chain":
|
|
62703
|
+
return [
|
|
62704
|
+
{
|
|
62705
|
+
id: "off-chain",
|
|
62706
|
+
kind: "queued",
|
|
62707
|
+
label: "Off-chain redemption",
|
|
62708
|
+
settlement: "async",
|
|
62709
|
+
waitSeconds: i.withdrawalCooldownSeconds,
|
|
62710
|
+
description: "Redemption is handled by the issuer off-chain; there is no on-chain exit to call."
|
|
62711
|
+
}
|
|
62712
|
+
];
|
|
62713
|
+
case "dex-only":
|
|
62714
|
+
case "market-sale":
|
|
62715
|
+
return [
|
|
62716
|
+
{
|
|
62717
|
+
id: "market",
|
|
62718
|
+
kind: "market",
|
|
62719
|
+
label: "Sell on the market",
|
|
62720
|
+
settlement: "market",
|
|
62721
|
+
description: "There is no redemption \u2014 you leave by selling the token, at whatever price is bid and with price impact that grows with size."
|
|
62722
|
+
}
|
|
62723
|
+
];
|
|
62724
|
+
default:
|
|
62725
|
+
return [];
|
|
62726
|
+
}
|
|
62727
|
+
};
|
|
62728
|
+
|
|
62113
62729
|
// src/vaults/lst/fetchPublic.ts
|
|
62114
62730
|
var ONE_E1812 = 10n ** 18n;
|
|
62115
62731
|
var ERC20_BALANCE_ABI = parseAbi([
|
|
@@ -62128,6 +62744,22 @@ var resolveAcceptedInputs = (chainId, shareToken, entry) => {
|
|
|
62128
62744
|
}
|
|
62129
62745
|
];
|
|
62130
62746
|
};
|
|
62747
|
+
var probeSelfOnly = (chainId, shareToken, route) => {
|
|
62748
|
+
try {
|
|
62749
|
+
const self = ignoresReceiver(buildLstWithdrawRequest, {
|
|
62750
|
+
chainId,
|
|
62751
|
+
shareToken,
|
|
62752
|
+
amount: 10n ** 18n,
|
|
62753
|
+
receiver: "0x00000000000000000000000000000000000000a1",
|
|
62754
|
+
// Neutral protocol-required inputs, so the probe measures the RECEIVER
|
|
62755
|
+
// and not a missing argument.
|
|
62756
|
+
options: { route, deadline: 9999999999n, minAssetOut: 0n, minHype: 0n }
|
|
62757
|
+
});
|
|
62758
|
+
return self ? true : void 0;
|
|
62759
|
+
} catch {
|
|
62760
|
+
return void 0;
|
|
62761
|
+
}
|
|
62762
|
+
};
|
|
62131
62763
|
var fetchLstShareTokens = async (chainId, multicallRetry, prices = {}, tokenList = {}, opts = {}) => {
|
|
62132
62764
|
const entries = getLstRegistry(chainId);
|
|
62133
62765
|
if (entries.length === 0) return {};
|
|
@@ -62237,6 +62869,7 @@ var fetchLstShareTokens = async (chainId, multicallRetry, prices = {}, tokenList
|
|
|
62237
62869
|
}
|
|
62238
62870
|
const liquidityFormatted = Number(liquidityRaw) / 10 ** underlyingDec;
|
|
62239
62871
|
const liquidityUsd = priceUsd !== void 0 ? liquidityFormatted * priceUsd : 0;
|
|
62872
|
+
const cooldownSecs = state.withdrawalCooldownSeconds ?? entry.withdrawalCooldownSeconds;
|
|
62240
62873
|
const displayName = composeVaultDisplayName(
|
|
62241
62874
|
entry.brand,
|
|
62242
62875
|
entry.brand,
|
|
@@ -62274,7 +62907,34 @@ var fetchLstShareTokens = async (chainId, multicallRetry, prices = {}, tokenList
|
|
|
62274
62907
|
delegation: delegationByAddress.get(addressLc),
|
|
62275
62908
|
validators: validatorsByAddress.get(addressLc),
|
|
62276
62909
|
withdrawalMode: entry.withdrawalMode,
|
|
62277
|
-
|
|
62910
|
+
// A reader-measured wait wins over the registry's static one — see
|
|
62911
|
+
// `LstOnChainState.withdrawalCooldownSeconds`.
|
|
62912
|
+
withdrawalCooldownSeconds: cooldownSecs,
|
|
62913
|
+
withdrawFeeBps: state.withdrawFeeBps,
|
|
62914
|
+
// A reader that reads its protocol's own per-leg dials publishes the
|
|
62915
|
+
// list itself; everything else gets the coarse derivation, which is
|
|
62916
|
+
// still strictly better than making every consumer reassemble the two
|
|
62917
|
+
// legs out of `withdrawalMode` + one cooldown + one liquidity number.
|
|
62918
|
+
exitRoutes: (state.exitRoutes ?? deriveExitRoutes({
|
|
62919
|
+
withdrawalMode: entry.withdrawalMode,
|
|
62920
|
+
withdrawFeeBps: state.withdrawFeeBps,
|
|
62921
|
+
withdrawalCooldownSeconds: cooldownSecs,
|
|
62922
|
+
liquidity: liquidityRaw.toString(),
|
|
62923
|
+
liquidityFormatted,
|
|
62924
|
+
liquidityUsd
|
|
62925
|
+
})).map(
|
|
62926
|
+
(r) => (
|
|
62927
|
+
// A reader that already established it wins; otherwise probe.
|
|
62928
|
+
r.selfOnly !== void 0 || r.kind === "market" ? r : {
|
|
62929
|
+
...r,
|
|
62930
|
+
selfOnly: probeSelfOnly(
|
|
62931
|
+
chainId,
|
|
62932
|
+
addressLc,
|
|
62933
|
+
r.kind === "instant" ? "instant" : "queued"
|
|
62934
|
+
)
|
|
62935
|
+
}
|
|
62936
|
+
)
|
|
62937
|
+
),
|
|
62278
62938
|
asset,
|
|
62279
62939
|
priceUsd,
|
|
62280
62940
|
totalAssetsFormatted,
|
|
@@ -62376,17 +63036,17 @@ var readerBeets = {
|
|
|
62376
63036
|
const out = [];
|
|
62377
63037
|
for (let i = 0; i < reqs.length; i++) {
|
|
62378
63038
|
const r = reqs[i];
|
|
62379
|
-
const
|
|
63039
|
+
const amount4 = toBigInt14(r.assetAmount);
|
|
62380
63040
|
const ts = toNumber(r.requestTimestamp);
|
|
62381
63041
|
const isWithdrawn = Boolean(r.isWithdrawn);
|
|
62382
|
-
if (
|
|
63042
|
+
if (amount4 === void 0 || ts === void 0) continue;
|
|
62383
63043
|
const readyAt = ts + delay;
|
|
62384
63044
|
out.push({
|
|
62385
63045
|
lst: entry.lst,
|
|
62386
63046
|
brand: entry.brand,
|
|
62387
63047
|
symbol: entry.symbol,
|
|
62388
63048
|
requestId: String(i),
|
|
62389
|
-
amountUnderlying:
|
|
63049
|
+
amountUnderlying: amount4.toString(),
|
|
62390
63050
|
status: isWithdrawn ? "claimed" : computeStatus(readyAt),
|
|
62391
63051
|
readyAt: isWithdrawn ? void 0 : readyAt
|
|
62392
63052
|
});
|
|
@@ -62837,8 +63497,8 @@ var readerIbera = {
|
|
|
62837
63497
|
const r = stage2[k];
|
|
62838
63498
|
if (!r) continue;
|
|
62839
63499
|
const receiver = Array.isArray(r) ? r[2] : r.receiver;
|
|
62840
|
-
const
|
|
62841
|
-
if (typeof receiver !== "string" || receiver.toLowerCase() !== target ||
|
|
63500
|
+
const amount4 = Array.isArray(r) ? toBigInt14(r[3]) : toBigInt14(r.amount);
|
|
63501
|
+
if (typeof receiver !== "string" || receiver.toLowerCase() !== target || amount4 === void 0 || amount4 === 0n) {
|
|
62842
63502
|
continue;
|
|
62843
63503
|
}
|
|
62844
63504
|
const id = BigInt(ids[k]);
|
|
@@ -62847,7 +63507,7 @@ var readerIbera = {
|
|
|
62847
63507
|
brand: entry.brand,
|
|
62848
63508
|
symbol: entry.symbol,
|
|
62849
63509
|
requestId: String(ids[k]),
|
|
62850
|
-
amountUnderlying:
|
|
63510
|
+
amountUnderlying: amount4.toString(),
|
|
62851
63511
|
status: id < frontier ? "claimable" : "pending"
|
|
62852
63512
|
});
|
|
62853
63513
|
}
|
|
@@ -63020,13 +63680,13 @@ var readerErc7540 = {
|
|
|
63020
63680
|
],
|
|
63021
63681
|
abi: [Erc7540Abi]
|
|
63022
63682
|
});
|
|
63023
|
-
const
|
|
63683
|
+
const amount4 = toBigInt14(stage2[0]) ?? claimable;
|
|
63024
63684
|
out.push({
|
|
63025
63685
|
lst: entry.lst,
|
|
63026
63686
|
brand: entry.brand,
|
|
63027
63687
|
symbol: entry.symbol,
|
|
63028
63688
|
requestId: "0",
|
|
63029
|
-
amountUnderlying:
|
|
63689
|
+
amountUnderlying: amount4.toString(),
|
|
63030
63690
|
// The 7540 claim (`redeem`) takes the share amount.
|
|
63031
63691
|
shares: claimable.toString(),
|
|
63032
63692
|
status: "claimable"
|
|
@@ -63075,15 +63735,15 @@ var readerEthenaCooldown = {
|
|
|
63075
63735
|
});
|
|
63076
63736
|
const cell = res[0];
|
|
63077
63737
|
let cooldownEnd;
|
|
63078
|
-
let
|
|
63738
|
+
let amount4;
|
|
63079
63739
|
if (Array.isArray(cell)) {
|
|
63080
63740
|
cooldownEnd = toBigInt14(cell[0]);
|
|
63081
|
-
|
|
63741
|
+
amount4 = toBigInt14(cell[1]);
|
|
63082
63742
|
} else if (cell && typeof cell === "object") {
|
|
63083
63743
|
cooldownEnd = toBigInt14(cell.cooldownEnd);
|
|
63084
|
-
|
|
63744
|
+
amount4 = toBigInt14(cell.underlyingAmount);
|
|
63085
63745
|
}
|
|
63086
|
-
if (!
|
|
63746
|
+
if (!amount4 || amount4 === 0n) return [];
|
|
63087
63747
|
const readyAt = Number(cooldownEnd ?? 0n);
|
|
63088
63748
|
const out = [
|
|
63089
63749
|
{
|
|
@@ -63091,7 +63751,7 @@ var readerEthenaCooldown = {
|
|
|
63091
63751
|
brand: entry.brand,
|
|
63092
63752
|
symbol: entry.symbol,
|
|
63093
63753
|
requestId: "0",
|
|
63094
|
-
amountUnderlying:
|
|
63754
|
+
amountUnderlying: amount4.toString(),
|
|
63095
63755
|
status: computeStatus(readyAt),
|
|
63096
63756
|
readyAt
|
|
63097
63757
|
}
|
|
@@ -63146,7 +63806,7 @@ var readerSusd3Cooldown = {
|
|
|
63146
63806
|
shares = toBigInt14(cell.shares);
|
|
63147
63807
|
}
|
|
63148
63808
|
if (!shares || shares === 0n) return [];
|
|
63149
|
-
let
|
|
63809
|
+
let amount4 = shares;
|
|
63150
63810
|
try {
|
|
63151
63811
|
const stage2 = await multicallRetry({
|
|
63152
63812
|
chain: chainId,
|
|
@@ -63155,7 +63815,7 @@ var readerSusd3Cooldown = {
|
|
|
63155
63815
|
],
|
|
63156
63816
|
abi: [Susd3CooldownStatusAbi]
|
|
63157
63817
|
});
|
|
63158
|
-
|
|
63818
|
+
amount4 = toBigInt14(stage2[0]) ?? shares;
|
|
63159
63819
|
} catch {
|
|
63160
63820
|
}
|
|
63161
63821
|
const readyAt = Number(cooldownEnd ?? 0n);
|
|
@@ -63166,7 +63826,7 @@ var readerSusd3Cooldown = {
|
|
|
63166
63826
|
brand: entry.brand,
|
|
63167
63827
|
symbol: entry.symbol,
|
|
63168
63828
|
requestId: "0",
|
|
63169
|
-
amountUnderlying:
|
|
63829
|
+
amountUnderlying: amount4.toString(),
|
|
63170
63830
|
shares: shares.toString(),
|
|
63171
63831
|
status: computeStatus(readyAt, expiresAt),
|
|
63172
63832
|
readyAt,
|
|
@@ -63362,14 +64022,14 @@ var readerEtherFi = {
|
|
|
63362
64022
|
const isValid = Boolean(stage3[i * 3 + 2]);
|
|
63363
64023
|
if (!req) continue;
|
|
63364
64024
|
if (!isValid) continue;
|
|
63365
|
-
const
|
|
63366
|
-
if (
|
|
64025
|
+
const amount4 = toBigInt14(req.amountOfEEth);
|
|
64026
|
+
if (amount4 === void 0) continue;
|
|
63367
64027
|
out.push({
|
|
63368
64028
|
lst: entry.lst,
|
|
63369
64029
|
brand: entry.brand,
|
|
63370
64030
|
symbol: entry.symbol,
|
|
63371
64031
|
requestId: id.toString(),
|
|
63372
|
-
amountUnderlying:
|
|
64032
|
+
amountUnderlying: amount4.toString(),
|
|
63373
64033
|
status: isFinalized ? "claimable" : "pending"
|
|
63374
64034
|
});
|
|
63375
64035
|
}
|
|
@@ -63699,15 +64359,15 @@ var readerLista = {
|
|
|
63699
64359
|
const isClaimable = Array.isArray(status) ? Boolean(status[0]) : Boolean(status._isClaimable);
|
|
63700
64360
|
const bnbAmount = Array.isArray(status) ? toBigInt14(status[1]) : toBigInt14(status._amount);
|
|
63701
64361
|
const snbnbAmount = Array.isArray(req) ? toBigInt14(req[1]) : toBigInt14(req?.amountInSnBnb);
|
|
63702
|
-
const
|
|
63703
|
-
if (
|
|
64362
|
+
const amount4 = bnbAmount ?? snbnbAmount;
|
|
64363
|
+
if (amount4 === void 0) continue;
|
|
63704
64364
|
const uuid = Array.isArray(req) ? toBigInt14(req[0]) : toBigInt14(req?.uuid);
|
|
63705
64365
|
out.push({
|
|
63706
64366
|
lst: entry.lst,
|
|
63707
64367
|
brand: entry.brand,
|
|
63708
64368
|
symbol: entry.symbol,
|
|
63709
64369
|
requestId: String(uuid ?? i),
|
|
63710
|
-
amountUnderlying:
|
|
64370
|
+
amountUnderlying: amount4.toString(),
|
|
63711
64371
|
status: isClaimable ? "claimable" : "pending"
|
|
63712
64372
|
});
|
|
63713
64373
|
}
|
|
@@ -63962,7 +64622,7 @@ var readerStaderMaticX2 = {
|
|
|
63962
64622
|
const out = [];
|
|
63963
64623
|
for (let i = 0; i < arr.length; i++) {
|
|
63964
64624
|
const r = arr[i];
|
|
63965
|
-
const
|
|
64625
|
+
const amount4 = toBigInt14(r.amount) ?? 0n;
|
|
63966
64626
|
const requestEpoch = toBigInt14(r.requestEpoch);
|
|
63967
64627
|
if (requestEpoch === void 0) continue;
|
|
63968
64628
|
const ready = stakeManager ? currentEpoch >= requestEpoch + delay : false;
|
|
@@ -63973,7 +64633,7 @@ var readerStaderMaticX2 = {
|
|
|
63973
64633
|
// Use array index as the request id (consistent with
|
|
63974
64634
|
// `claimWithdrawal(uint256 _idx)`).
|
|
63975
64635
|
requestId: String(i),
|
|
63976
|
-
amountUnderlying:
|
|
64636
|
+
amountUnderlying: amount4.toString(),
|
|
63977
64637
|
status: ready ? "claimable" : "pending"
|
|
63978
64638
|
});
|
|
63979
64639
|
}
|
|
@@ -64374,7 +65034,7 @@ var readerStakeWise = {
|
|
|
64374
65034
|
const out = [];
|
|
64375
65035
|
for (let i = 0; i < requests.length; i++) {
|
|
64376
65036
|
const r = requests[i];
|
|
64377
|
-
const
|
|
65037
|
+
const amount4 = toBigInt14(r.totalAssets) ?? 0n;
|
|
64378
65038
|
const onChainClaimed = claimedByIdx.get(i);
|
|
64379
65039
|
const claimable = onChainClaimed !== void 0 || r.isClaimable;
|
|
64380
65040
|
out.push({
|
|
@@ -64382,7 +65042,7 @@ var readerStakeWise = {
|
|
|
64382
65042
|
brand: entry.brand,
|
|
64383
65043
|
symbol: entry.symbol,
|
|
64384
65044
|
requestId: r.positionTicket,
|
|
64385
|
-
amountUnderlying: (onChainClaimed ??
|
|
65045
|
+
amountUnderlying: (onChainClaimed ?? amount4).toString(),
|
|
64386
65046
|
status: claimable ? "claimable" : "pending"
|
|
64387
65047
|
});
|
|
64388
65048
|
}
|
|
@@ -64431,15 +65091,15 @@ var readerStCelo2 = {
|
|
|
64431
65091
|
const timestamps = cell[1] ?? [];
|
|
64432
65092
|
const out = [];
|
|
64433
65093
|
for (let i = 0; i < values.length; i++) {
|
|
64434
|
-
const
|
|
65094
|
+
const amount4 = toBigInt14(values[i]);
|
|
64435
65095
|
const readyAt = toNumber(timestamps[i]);
|
|
64436
|
-
if (
|
|
65096
|
+
if (amount4 === void 0 || readyAt === void 0) continue;
|
|
64437
65097
|
out.push({
|
|
64438
65098
|
lst: entry.lst,
|
|
64439
65099
|
brand: entry.brand,
|
|
64440
65100
|
symbol: entry.symbol,
|
|
64441
65101
|
requestId: String(i),
|
|
64442
|
-
amountUnderlying:
|
|
65102
|
+
amountUnderlying: amount4.toString(),
|
|
64443
65103
|
status: computeStatus(readyAt),
|
|
64444
65104
|
readyAt
|
|
64445
65105
|
});
|
|
@@ -64540,15 +65200,15 @@ var readerSwell = {
|
|
|
64540
65200
|
const id = ids[i];
|
|
64541
65201
|
const r = stage3[i];
|
|
64542
65202
|
if (!r) continue;
|
|
64543
|
-
const
|
|
64544
|
-
if (
|
|
65203
|
+
const amount4 = toBigInt14(r.amount);
|
|
65204
|
+
if (amount4 === void 0) continue;
|
|
64545
65205
|
const claimable = id <= lastProcessed;
|
|
64546
65206
|
out.push({
|
|
64547
65207
|
lst: entry.lst,
|
|
64548
65208
|
brand: entry.brand,
|
|
64549
65209
|
symbol: entry.symbol,
|
|
64550
65210
|
requestId: id.toString(),
|
|
64551
|
-
amountUnderlying:
|
|
65211
|
+
amountUnderlying: amount4.toString(),
|
|
64552
65212
|
status: claimable ? "claimable" : "pending"
|
|
64553
65213
|
});
|
|
64554
65214
|
}
|
|
@@ -64614,15 +65274,15 @@ var readerValantis = {
|
|
|
64614
65274
|
for (let i = 0; i < burns.length; i++) {
|
|
64615
65275
|
const b = burns[i];
|
|
64616
65276
|
if (!b) continue;
|
|
64617
|
-
const
|
|
65277
|
+
const amount4 = Array.isArray(b) ? toBigInt14(b[0]) : toBigInt14(b.amount);
|
|
64618
65278
|
const completed = Array.isArray(b) ? Boolean(b[2]) : Boolean(b.completed);
|
|
64619
|
-
if (
|
|
65279
|
+
if (amount4 === void 0 || completed) continue;
|
|
64620
65280
|
out.push({
|
|
64621
65281
|
lst: entry.lst,
|
|
64622
65282
|
brand: entry.brand,
|
|
64623
65283
|
symbol: entry.symbol,
|
|
64624
65284
|
requestId: String(toBigInt14(ids[i]) ?? i),
|
|
64625
|
-
amountUnderlying:
|
|
65285
|
+
amountUnderlying: amount4.toString(),
|
|
64626
65286
|
status: redeemable[i] ? "claimable" : "pending"
|
|
64627
65287
|
});
|
|
64628
65288
|
}
|
|
@@ -64630,6 +65290,84 @@ var readerValantis = {
|
|
|
64630
65290
|
}
|
|
64631
65291
|
};
|
|
64632
65292
|
|
|
65293
|
+
// src/vaults/lst/withdrawals/abis/treehouse.ts
|
|
65294
|
+
var TreehouseRedemptionQueueAbi = [
|
|
65295
|
+
{
|
|
65296
|
+
name: "getPendingRedeems",
|
|
65297
|
+
type: "function",
|
|
65298
|
+
stateMutability: "view",
|
|
65299
|
+
inputs: [{ type: "address", name: "user" }],
|
|
65300
|
+
outputs: [
|
|
65301
|
+
{
|
|
65302
|
+
type: "tuple[]",
|
|
65303
|
+
components: [
|
|
65304
|
+
{ type: "uint64", name: "startTime" },
|
|
65305
|
+
{ type: "uint96", name: "shares" },
|
|
65306
|
+
{ type: "uint128", name: "assets" },
|
|
65307
|
+
{ type: "uint128", name: "baseRate" }
|
|
65308
|
+
]
|
|
65309
|
+
}
|
|
65310
|
+
]
|
|
65311
|
+
},
|
|
65312
|
+
{
|
|
65313
|
+
name: "waitingPeriod",
|
|
65314
|
+
type: "function",
|
|
65315
|
+
stateMutability: "view",
|
|
65316
|
+
inputs: [],
|
|
65317
|
+
outputs: [{ type: "uint32" }]
|
|
65318
|
+
}
|
|
65319
|
+
];
|
|
65320
|
+
|
|
65321
|
+
// src/vaults/lst/withdrawals/readers/treehouse.ts
|
|
65322
|
+
var readerTreehouseRedemption = {
|
|
65323
|
+
fetch: async (user, multicallRetry, chainId, entry) => {
|
|
65324
|
+
if (!entry.withdrawalContract) return [];
|
|
65325
|
+
const res = await multicallRetry({
|
|
65326
|
+
chain: chainId,
|
|
65327
|
+
calls: [
|
|
65328
|
+
{
|
|
65329
|
+
address: entry.withdrawalContract,
|
|
65330
|
+
name: "getPendingRedeems",
|
|
65331
|
+
params: [user]
|
|
65332
|
+
},
|
|
65333
|
+
{
|
|
65334
|
+
address: entry.withdrawalContract,
|
|
65335
|
+
name: "waitingPeriod",
|
|
65336
|
+
params: []
|
|
65337
|
+
}
|
|
65338
|
+
],
|
|
65339
|
+
abi: [
|
|
65340
|
+
TreehouseRedemptionQueueAbi,
|
|
65341
|
+
TreehouseRedemptionQueueAbi
|
|
65342
|
+
]
|
|
65343
|
+
});
|
|
65344
|
+
const reqs = res[0];
|
|
65345
|
+
const waitingPeriod = toNumber(res[1]);
|
|
65346
|
+
if (!Array.isArray(reqs) || waitingPeriod === void 0) return [];
|
|
65347
|
+
const out = [];
|
|
65348
|
+
for (let i = 0; i < reqs.length; i++) {
|
|
65349
|
+
const r = reqs[i];
|
|
65350
|
+
const startTime = toNumber(r.startTime);
|
|
65351
|
+
const assets = toBigInt14(r.assets);
|
|
65352
|
+
const shares = toBigInt14(r.shares);
|
|
65353
|
+
if (startTime === void 0 || assets === void 0) continue;
|
|
65354
|
+
const readyAt = startTime + waitingPeriod;
|
|
65355
|
+
out.push({
|
|
65356
|
+
lst: entry.lst,
|
|
65357
|
+
brand: entry.brand,
|
|
65358
|
+
symbol: entry.symbol,
|
|
65359
|
+
// Positional — see note 1 above.
|
|
65360
|
+
requestId: String(i),
|
|
65361
|
+
amountUnderlying: assets.toString(),
|
|
65362
|
+
shares: shares?.toString(),
|
|
65363
|
+
status: computeStatus(readyAt),
|
|
65364
|
+
readyAt
|
|
65365
|
+
});
|
|
65366
|
+
}
|
|
65367
|
+
return out;
|
|
65368
|
+
}
|
|
65369
|
+
};
|
|
65370
|
+
|
|
64633
65371
|
// src/vaults/lst/withdrawals/abis/trufin.ts
|
|
64634
65372
|
var TruFinVaultAbi = [
|
|
64635
65373
|
{
|
|
@@ -64694,15 +65432,15 @@ var readerTruFin = {
|
|
|
64694
65432
|
if (typeof recipient === "string" && recipient.toLowerCase() !== lcUser) {
|
|
64695
65433
|
continue;
|
|
64696
65434
|
}
|
|
64697
|
-
const
|
|
64698
|
-
if (
|
|
65435
|
+
const amount4 = Array.isArray(w) ? toBigInt14(w[1]) : toBigInt14(w.amount);
|
|
65436
|
+
if (amount4 === void 0 || amount4 === 0n) continue;
|
|
64699
65437
|
out.push({
|
|
64700
65438
|
lst: entry.lst,
|
|
64701
65439
|
brand: entry.brand,
|
|
64702
65440
|
symbol: entry.symbol,
|
|
64703
65441
|
// Composite id — same shape as the input.
|
|
64704
65442
|
requestId: `${pairs[i].validator}:${pairs[i].nonce.toString()}`,
|
|
64705
|
-
amountUnderlying:
|
|
65443
|
+
amountUnderlying: amount4.toString(),
|
|
64706
65444
|
status: claimable ? "claimable" : "pending"
|
|
64707
65445
|
});
|
|
64708
65446
|
}
|
|
@@ -64809,17 +65547,17 @@ var readerYieldNest = {
|
|
|
64809
65547
|
const id = ids[i];
|
|
64810
65548
|
const r = stage3[i];
|
|
64811
65549
|
if (!r) continue;
|
|
64812
|
-
const
|
|
65550
|
+
const amount4 = toBigInt14(r.amount);
|
|
64813
65551
|
const created = toNumber(r.creationTimestamp);
|
|
64814
65552
|
const processed = Boolean(r.processed);
|
|
64815
|
-
if (
|
|
65553
|
+
if (amount4 === void 0 || created === void 0) continue;
|
|
64816
65554
|
const readyAt = created + finalizationSeconds;
|
|
64817
65555
|
out.push({
|
|
64818
65556
|
lst: entry.lst,
|
|
64819
65557
|
brand: entry.brand,
|
|
64820
65558
|
symbol: entry.symbol,
|
|
64821
65559
|
requestId: id.toString(),
|
|
64822
|
-
amountUnderlying:
|
|
65560
|
+
amountUnderlying: amount4.toString(),
|
|
64823
65561
|
status: processed ? "claimed" : computeStatus(readyAt),
|
|
64824
65562
|
readyAt: processed ? void 0 : readyAt
|
|
64825
65563
|
});
|
|
@@ -64888,6 +65626,8 @@ var buildWithdrawalReader = (entry) => {
|
|
|
64888
65626
|
return readerPrimeStaking;
|
|
64889
65627
|
case "berapawRedeemQueue":
|
|
64890
65628
|
return readerBeraPaw;
|
|
65629
|
+
case "treehouseRedemptionQueue":
|
|
65630
|
+
return readerTreehouseRedemption;
|
|
64891
65631
|
case "eventsOnly":
|
|
64892
65632
|
case "noQueue":
|
|
64893
65633
|
case "unverified":
|
|
@@ -64898,6 +65638,18 @@ var buildWithdrawalReader = (entry) => {
|
|
|
64898
65638
|
// src/vaults/lst/withdrawals/registry.ts
|
|
64899
65639
|
var LST_WITHDRAWAL_REGISTRY = {
|
|
64900
65640
|
"1": [
|
|
65641
|
+
{
|
|
65642
|
+
// Treehouse tETH — `TreehouseRedemptionV2`, the queued (5 bps / 7 d)
|
|
65643
|
+
// exit. The instant Fastlane leg settles in the same transaction and
|
|
65644
|
+
// so never produces a pending request. Undocumented address,
|
|
65645
|
+
// recovered from `Vault.redemption()` →
|
|
65646
|
+
// `RedemptionController.getRedemptionContracts()`.
|
|
65647
|
+
lst: "0xd11c452fc99cf405034ee446803b6f6c1f6d5ed8",
|
|
65648
|
+
brand: "Treehouse",
|
|
65649
|
+
symbol: "tETH",
|
|
65650
|
+
reader: "treehouseRedemptionQueue",
|
|
65651
|
+
withdrawalContract: "0xcd63a29faff07130d3af89bb4f40778938aabb85"
|
|
65652
|
+
},
|
|
64901
65653
|
{
|
|
64902
65654
|
// wBETH — Binance's UnwrapTokenV1 queue, the SAME contract address
|
|
64903
65655
|
// on Ethereum and BNB. Entered via `wBETH.requestWithdrawEth`;
|
|
@@ -65361,6 +66113,14 @@ var LST_WITHDRAWAL_REGISTRY = {
|
|
|
65361
66113
|
}
|
|
65362
66114
|
],
|
|
65363
66115
|
"43114": [
|
|
66116
|
+
{
|
|
66117
|
+
// Treehouse tAVAX — same stack as tETH; 17-day wait here.
|
|
66118
|
+
lst: "0x14a84f1a61ccd7d1be596a6cc11fe33a36bc1646",
|
|
66119
|
+
brand: "Treehouse",
|
|
66120
|
+
symbol: "tAVAX",
|
|
66121
|
+
reader: "treehouseRedemptionQueue",
|
|
66122
|
+
withdrawalContract: "0x765f6dc8496ca7ef1e4a391be10185229aacf04b"
|
|
66123
|
+
},
|
|
65364
66124
|
// Ankr ankrAVAX — Ankr unstake queue; reader not yet implemented.
|
|
65365
66125
|
{
|
|
65366
66126
|
lst: "0xc3344870d52688874b06d844e0c36cc39fc727f6",
|
|
@@ -65431,6 +66191,14 @@ var LST_WITHDRAWAL_REGISTRY = {
|
|
|
65431
66191
|
}
|
|
65432
66192
|
],
|
|
65433
66193
|
"999": [
|
|
66194
|
+
{
|
|
66195
|
+
// Treehouse tHYPE — same stack as tETH; 10-day wait here.
|
|
66196
|
+
lst: "0xb83d27f0f4133a7b0377a88089583131a903fdc7",
|
|
66197
|
+
brand: "Treehouse",
|
|
66198
|
+
symbol: "tHYPE",
|
|
66199
|
+
reader: "treehouseRedemptionQueue",
|
|
66200
|
+
withdrawalContract: "0xcebbb011c2f29b0ed25895c54662bd1ccad30280"
|
|
66201
|
+
},
|
|
65434
66202
|
{
|
|
65435
66203
|
// Hyperbeat hbHYPE Ultra — ERC-7540 async-redeem.
|
|
65436
66204
|
lst: "0x96c6cbb6251ee1c257b2162ca0f39aa5fa44b1fb",
|
|
@@ -65670,6 +66438,15 @@ var Erc4626ReadAbi2 = [
|
|
|
65670
66438
|
outputs: [{ type: "uint256", name: "assets" }]
|
|
65671
66439
|
}
|
|
65672
66440
|
];
|
|
66441
|
+
var LockupPeriodAbi = [
|
|
66442
|
+
{
|
|
66443
|
+
name: "lockupPeriod",
|
|
66444
|
+
type: "function",
|
|
66445
|
+
stateMutability: "view",
|
|
66446
|
+
inputs: [],
|
|
66447
|
+
outputs: [{ type: "uint256" }]
|
|
66448
|
+
}
|
|
66449
|
+
];
|
|
65673
66450
|
var CooldownDurationAbi = [
|
|
65674
66451
|
{
|
|
65675
66452
|
name: "cooldownDuration",
|
|
@@ -65770,14 +66547,16 @@ var readerErc46262 = (entry) => {
|
|
|
65770
66547
|
var readerErc4626Cooldown = (entry) => {
|
|
65771
66548
|
const shareUnit = 10n ** BigInt(entry.decimals);
|
|
65772
66549
|
const underlyingUnit = 10n ** BigInt(entry.underlyingDecimals ?? entry.decimals);
|
|
66550
|
+
const cooldownGetter = entry.cooldownGetter ?? "cooldownDuration";
|
|
66551
|
+
const cooldownAbi = cooldownGetter === "lockupPeriod" ? LockupPeriodAbi : CooldownDurationAbi;
|
|
65773
66552
|
return {
|
|
65774
66553
|
calls: [
|
|
65775
66554
|
{ address: entry.address, name: "totalAssets", params: [] },
|
|
65776
66555
|
{ address: entry.address, name: "totalSupply", params: [] },
|
|
65777
66556
|
{ address: entry.address, name: "convertToAssets", params: [shareUnit] },
|
|
65778
|
-
{ address: entry.address, name:
|
|
66557
|
+
{ address: entry.address, name: cooldownGetter, params: [] }
|
|
65779
66558
|
],
|
|
65780
|
-
abis: [Erc4626ReadAbi2, TotalSupplyAbi2, Erc4626ReadAbi2,
|
|
66559
|
+
abis: [Erc4626ReadAbi2, TotalSupplyAbi2, Erc4626ReadAbi2, cooldownAbi],
|
|
65781
66560
|
parse: ([assets, supply, rate, cooldown]) => {
|
|
65782
66561
|
const totalAssets = toBigInt15(assets);
|
|
65783
66562
|
const totalSupply = toBigInt15(supply);
|
|
@@ -66255,6 +67034,8 @@ var readerHyperbeatVault = (entry) => {
|
|
|
66255
67034
|
var readerNavOracle = (entry) => {
|
|
66256
67035
|
const shareUnit = 10n ** BigInt(entry.decimals);
|
|
66257
67036
|
const underlyingUnit = 10n ** BigInt(entry.underlyingDecimals ?? entry.decimals);
|
|
67037
|
+
const oracleDecimals = entry.priceOracleDecimals ?? 18;
|
|
67038
|
+
const oracleScale = 10n ** BigInt(oracleDecimals);
|
|
66258
67039
|
return {
|
|
66259
67040
|
calls: [
|
|
66260
67041
|
{ address: entry.address, name: "totalSupply", params: [] },
|
|
@@ -66269,8 +67050,9 @@ var readerNavOracle = (entry) => {
|
|
|
66269
67050
|
const totalSupply = toBigInt15(supply);
|
|
66270
67051
|
if (totalSupply === void 0) return void 0;
|
|
66271
67052
|
const raw = Array.isArray(round) ? round[1] : round?.answer;
|
|
66272
|
-
const
|
|
66273
|
-
if (
|
|
67053
|
+
const answer = toBigInt15(raw);
|
|
67054
|
+
if (answer === void 0 || answer <= 0n) return void 0;
|
|
67055
|
+
const exchangeRate = answer * ONE_E1813 / oracleScale;
|
|
66274
67056
|
return {
|
|
66275
67057
|
totalAssets: totalSupply * exchangeRate * underlyingUnit / (ONE_E1813 * shareUnit),
|
|
66276
67058
|
totalSupply,
|
|
@@ -66453,6 +67235,14 @@ var resolveYieldApr2 = async (entries) => (await resolveEntryApr(entries)).apr;
|
|
|
66453
67235
|
|
|
66454
67236
|
// src/vaults/savings/fetchPublic.ts
|
|
66455
67237
|
var ONE_E1814 = 10n ** 18n;
|
|
67238
|
+
var resolveSelfOnly = (chainId, vault) => {
|
|
67239
|
+
const entry = findSavingsWithdrawEntry(chainId, vault);
|
|
67240
|
+
if (!entry) return void 0;
|
|
67241
|
+
return SAVINGS_RECEIVER_CAPABILITY[entry.kind]?.exit === false ? true : void 0;
|
|
67242
|
+
};
|
|
67243
|
+
var withSelfOnly = (routes2, selfOnly) => selfOnly === void 0 ? routes2 : routes2.map(
|
|
67244
|
+
(r) => r.kind === "market" || r.selfOnly !== void 0 ? r : { ...r, selfOnly }
|
|
67245
|
+
);
|
|
66456
67246
|
var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList = {}) => {
|
|
66457
67247
|
const entries = getSavingsRegistry(chainId);
|
|
66458
67248
|
if (entries.length === 0) return {};
|
|
@@ -66570,6 +67360,22 @@ var fetchSavingsVaults = async (chainId, multicallRetry, prices = {}, tokenList
|
|
|
66570
67360
|
instantRedeemEnabled: state.instantRedeemEnabled,
|
|
66571
67361
|
inventoryContract: entry.inventoryContract?.toLowerCase(),
|
|
66572
67362
|
withdrawQueue: state.withdrawQueue ?? entry.withdrawQueue?.toLowerCase(),
|
|
67363
|
+
// Both legs of a two-legged exit, spelled out — see `VaultExitRoute`.
|
|
67364
|
+
// Derived from the flat fields the readers already establish, so every
|
|
67365
|
+
// savings row gets it without a per-provider change; the queued leg's
|
|
67366
|
+
// fee is left ABSENT rather than 0 because "not published" and "free"
|
|
67367
|
+
// are different claims and only some protocols make the second.
|
|
67368
|
+
exitRoutes: withSelfOnly(
|
|
67369
|
+
deriveExitRoutes({
|
|
67370
|
+
withdrawalMode: entry.withdrawalMode,
|
|
67371
|
+
withdrawFeeBps: state.withdrawFeeBps,
|
|
67372
|
+
withdrawalCooldownSeconds: state.withdrawalCooldownSeconds ?? entry.withdrawalCooldownSeconds,
|
|
67373
|
+
liquidity: liquidityRaw,
|
|
67374
|
+
liquidityFormatted,
|
|
67375
|
+
liquidityUsd
|
|
67376
|
+
}),
|
|
67377
|
+
resolveSelfOnly(chainId, entry.address)
|
|
67378
|
+
),
|
|
66573
67379
|
depositCapacity,
|
|
66574
67380
|
depositCapacityFormatted,
|
|
66575
67381
|
depositCapacityUsd,
|
|
@@ -67186,6 +67992,34 @@ var fetchUpshiftVaults = async (chainId, prices = {}, tokenList = {}) => {
|
|
|
67186
67992
|
return out;
|
|
67187
67993
|
};
|
|
67188
67994
|
|
|
67995
|
+
// src/vaults/rateSanity.ts
|
|
67996
|
+
var NOISE_DEVIATION_BPS = 10;
|
|
67997
|
+
var IMPLAUSIBLE_APR_PERCENT2 = 1e3;
|
|
67998
|
+
var DUST_TVL_USD = 1e3;
|
|
67999
|
+
var impliedDeviationBps = (c) => {
|
|
68000
|
+
const secs = c.expiry - c.nowSecs;
|
|
68001
|
+
if (!(secs > 0)) return 0;
|
|
68002
|
+
const years = secs / 31536e3;
|
|
68003
|
+
return (Math.pow(1 + c.aprPercent / 100, years) - 1) * 1e4;
|
|
68004
|
+
};
|
|
68005
|
+
var isAnnualizationNoise = (c) => {
|
|
68006
|
+
if (!Number.isFinite(c.aprPercent)) return false;
|
|
68007
|
+
if (!(c.expiry > c.nowSecs)) return false;
|
|
68008
|
+
return Math.abs(impliedDeviationBps(c)) < NOISE_DEVIATION_BPS;
|
|
68009
|
+
};
|
|
68010
|
+
var isImplausibleMagnitude = (aprPercent, totalAssetsUsd) => {
|
|
68011
|
+
if (!Number.isFinite(aprPercent)) return false;
|
|
68012
|
+
if (Math.abs(aprPercent) <= IMPLAUSIBLE_APR_PERCENT2) return false;
|
|
68013
|
+
return (totalAssetsUsd ?? 0) < DUST_TVL_USD;
|
|
68014
|
+
};
|
|
68015
|
+
var isUnearnableRate = (args) => {
|
|
68016
|
+
const { aprPercent, totalAssetsUsd, expiry } = args;
|
|
68017
|
+
if (isImplausibleMagnitude(aprPercent, totalAssetsUsd)) return true;
|
|
68018
|
+
if (expiry === void 0) return false;
|
|
68019
|
+
const nowSecs = args.nowSecs ?? Math.floor(Date.now() / 1e3);
|
|
68020
|
+
return (totalAssetsUsd ?? 0) < DUST_TVL_USD && isAnnualizationNoise({ aprPercent, expiry, nowSecs });
|
|
68021
|
+
};
|
|
68022
|
+
|
|
67189
68023
|
// src/vaults/yearn/fetchPublic.ts
|
|
67190
68024
|
var BRAND3 = "Yearn";
|
|
67191
68025
|
var ZERO_ADDR = "0x0000000000000000000000000000000000000000";
|
|
@@ -67375,7 +68209,14 @@ var fetchYearnVaults = async (chainId, multicallRetry, prices = {}, tokenList =
|
|
|
67375
68209
|
const out = {};
|
|
67376
68210
|
for (const item of items) {
|
|
67377
68211
|
const parsed = parseVault9(item, chainId, prices, tokenList);
|
|
67378
|
-
if (parsed)
|
|
68212
|
+
if (!parsed) continue;
|
|
68213
|
+
if (isUnearnableRate({
|
|
68214
|
+
aprPercent: parsed.supplyRate,
|
|
68215
|
+
totalAssetsUsd: parsed.totalAssetsUsd
|
|
68216
|
+
})) {
|
|
68217
|
+
continue;
|
|
68218
|
+
}
|
|
68219
|
+
out[parsed.address] = parsed;
|
|
67379
68220
|
}
|
|
67380
68221
|
try {
|
|
67381
68222
|
await attachYearnLiquidity(chainId, multicallRetry, out);
|
|
@@ -69137,7 +69978,16 @@ var fetchPendlePtMarkets = async (chainId, multicallRetry, prices = {}, tokenLis
|
|
|
69137
69978
|
decimalsOnChain,
|
|
69138
69979
|
nowSecs
|
|
69139
69980
|
);
|
|
69140
|
-
if (parsed)
|
|
69981
|
+
if (!parsed) continue;
|
|
69982
|
+
if (isUnearnableRate({
|
|
69983
|
+
aprPercent: parsed.supplyRate,
|
|
69984
|
+
totalAssetsUsd: parsed.totalAssetsUsd,
|
|
69985
|
+
expiry: parsed.expiry,
|
|
69986
|
+
nowSecs
|
|
69987
|
+
})) {
|
|
69988
|
+
continue;
|
|
69989
|
+
}
|
|
69990
|
+
out[parsed.address] = parsed;
|
|
69141
69991
|
}
|
|
69142
69992
|
return out;
|
|
69143
69993
|
};
|
|
@@ -69386,7 +70236,16 @@ var fetchSpectraPtMarkets = async (chainId, multicallRetry, prices = {}, tokenLi
|
|
|
69386
70236
|
decimalsOnChain,
|
|
69387
70237
|
nowSecs
|
|
69388
70238
|
);
|
|
69389
|
-
if (parsed)
|
|
70239
|
+
if (!parsed) continue;
|
|
70240
|
+
if (isUnearnableRate({
|
|
70241
|
+
aprPercent: parsed.supplyRate,
|
|
70242
|
+
totalAssetsUsd: parsed.totalAssetsUsd,
|
|
70243
|
+
expiry: parsed.expiry,
|
|
70244
|
+
nowSecs
|
|
70245
|
+
})) {
|
|
70246
|
+
continue;
|
|
70247
|
+
}
|
|
70248
|
+
out[parsed.address] = parsed;
|
|
69390
70249
|
}
|
|
69391
70250
|
return out;
|
|
69392
70251
|
};
|
|
@@ -69714,24 +70573,24 @@ function shortDate(unixSecs) {
|
|
|
69714
70573
|
}
|
|
69715
70574
|
function feePhrase(fee) {
|
|
69716
70575
|
const magnitude = Math.abs(fee.value);
|
|
69717
|
-
let
|
|
70576
|
+
let amount4;
|
|
69718
70577
|
switch (fee.unit) {
|
|
69719
70578
|
case "bps":
|
|
69720
|
-
|
|
70579
|
+
amount4 = `${magnitude} bps`;
|
|
69721
70580
|
break;
|
|
69722
70581
|
case "apr-percent":
|
|
69723
|
-
|
|
70582
|
+
amount4 = `${pct(magnitude)}/yr`;
|
|
69724
70583
|
break;
|
|
69725
70584
|
case "percent":
|
|
69726
|
-
|
|
70585
|
+
amount4 = pct(magnitude);
|
|
69727
70586
|
break;
|
|
69728
70587
|
default:
|
|
69729
|
-
|
|
70588
|
+
amount4 = String(magnitude);
|
|
69730
70589
|
}
|
|
69731
70590
|
const rebate = fee.value < 0 ? " rebate" : "";
|
|
69732
70591
|
const qualifier = fee.indicative ? " (estimated, resolved at execution)" : "";
|
|
69733
70592
|
const bound = fee.mutable && fee.cap != null ? `, governance-set up to a maximum of ${fee.unit === "bps" ? `${fee.cap} bps` : pct(fee.cap)}` : fee.mutable ? ", governance-set" : "";
|
|
69734
|
-
return `${fee.label}: ${
|
|
70593
|
+
return `${fee.label}: ${amount4}${rebate}${bound}${qualifier}`;
|
|
69735
70594
|
}
|
|
69736
70595
|
function maturityPhrase(m) {
|
|
69737
70596
|
if (m.kind === "fixed-date" && m.maturity)
|
|
@@ -69817,12 +70676,40 @@ function provenance(rate) {
|
|
|
69817
70676
|
}
|
|
69818
70677
|
return ` (incl. ${pct(intrinsic)} from the asset)`;
|
|
69819
70678
|
}
|
|
69820
|
-
function
|
|
70679
|
+
function routePhrase(r, symbol) {
|
|
70680
|
+
const when = r.kind === "instant" ? "instantly" : r.waitSeconds ? `after ${duration(r.waitSeconds)}` : r.kind === "market" ? "by selling it" : "after a wait";
|
|
70681
|
+
const cost = r.feeBps === 0 ? " free" : r.feeBps != null ? ` for ${(r.feeBps / 100).toFixed(2)} %` : r.feeUnknown ? " for a fee" : "";
|
|
70682
|
+
const floor = r.minAmountFormatted != null && r.minAmountFormatted > 0 ? ` (min ${amount(r.minAmountFormatted)}${symbol ? ` ${symbol}` : ""})` : "";
|
|
70683
|
+
const cap = r.kind !== "instant" || r.capacityFormatted == null ? "" : r.capacityFormatted <= 0 ? ", though nothing is available right now" : `, up to ${amount(r.capacityFormatted)}${symbol ? ` ${symbol}` : ""} right now`;
|
|
70684
|
+
return `${when}${cost}${floor}${cap}`;
|
|
70685
|
+
}
|
|
70686
|
+
function routesSentence(routes2, symbol) {
|
|
70687
|
+
const legs = routes2.map((r) => routePhrase(r, symbol));
|
|
70688
|
+
const body = legs.length === 1 ? legs[0] : `${legs.slice(0, -1).join(", ")}, or ${legs[legs.length - 1]}`;
|
|
70689
|
+
return `You can leave ${body}.`;
|
|
70690
|
+
}
|
|
70691
|
+
function amount(v) {
|
|
70692
|
+
if (v >= 1e3) return v.toLocaleString("en-US", { maximumFractionDigits: 0 });
|
|
70693
|
+
if (v >= 1) return v.toFixed(2).replace(/\.?0+$/, "");
|
|
70694
|
+
return v.toPrecision(3);
|
|
70695
|
+
}
|
|
70696
|
+
function headlineExitFromRoutes(routes2, symbol) {
|
|
70697
|
+
if (!routes2 || routes2.length < 2) return void 0;
|
|
70698
|
+
const fast = routes2.find((r) => r.kind === "instant");
|
|
70699
|
+
const slow = routes2.find((r) => r.kind === "queued");
|
|
70700
|
+
if (!fast || !slow) return void 0;
|
|
70701
|
+
const fastPart = fast.feeBps == null ? "instant exit" : fast.feeBps === 0 ? "free instant exit" : `instant exit for ${(fast.feeBps / 100).toFixed(2)} %`;
|
|
70702
|
+
const slowCost = slow.feeBps === 0 ? "free" : slow.feeBps != null ? `${(slow.feeBps / 100).toFixed(2)} %` : void 0;
|
|
70703
|
+
const floor = slow.minAmountFormatted != null && slow.minAmountFormatted > 0 ? ` above ${amount(slow.minAmountFormatted)}${symbol ? ` ${symbol}` : ""}` : "";
|
|
70704
|
+
const slowPart = slowCost ? `queue${floor} for ${slowCost}` : `queue${floor}`;
|
|
70705
|
+
return `${fastPart}, or ${slowPart}`;
|
|
70706
|
+
}
|
|
70707
|
+
function supplyHeadline(s, sheet = {}) {
|
|
69821
70708
|
if (s.role === "collateral") {
|
|
69822
70709
|
return `Collateral only \xB7 ${maturityPhrase(s.maturity)}`;
|
|
69823
70710
|
}
|
|
69824
70711
|
const rate = `${rateLabel(s)} ${pct(s.rate.aprTotal)}${windowNote(s.rate)}${provenance(s.rate)}`;
|
|
69825
|
-
const exit = exitPhrase[String(s.exit.mode)] ?? (s.exit.settlement === "sync" ? "withdraw any time" : "delayed withdrawal");
|
|
70712
|
+
const exit = headlineExitFromRoutes(s.exit.routes, sheet.asset?.symbol) ?? exitPhrase[String(s.exit.mode)] ?? (s.exit.settlement === "sync" ? "withdraw any time" : "delayed withdrawal");
|
|
69826
70713
|
const cooldown = s.exit.cooldownSecs ? ` (${duration(s.exit.cooldownSecs)})` : "";
|
|
69827
70714
|
const mat = s.maturity.kind === "perpetual" ? "" : ` ${maturityPhrase(s.maturity)}`;
|
|
69828
70715
|
const warmup = s.rate.warmupSecs ? ` \xB7 earns after ${duration(s.rate.warmupSecs)}` : "";
|
|
@@ -69858,7 +70745,9 @@ function supplyDescription(s, sheet = {}) {
|
|
|
69858
70745
|
`You earn ${pct(s.rate.aprTotal)} (${comp.join(" + ")}), ${rateBehaviour(s.rate)}.`
|
|
69859
70746
|
);
|
|
69860
70747
|
}
|
|
69861
|
-
if (s.exit.
|
|
70748
|
+
if (s.exit.routes && s.exit.routes.length > 1) {
|
|
70749
|
+
parts.push(routesSentence(s.exit.routes, sheet.asset?.symbol));
|
|
70750
|
+
} else if (s.exit.mode === "instant") {
|
|
69862
70751
|
const util = sheet.utilization?.utilization;
|
|
69863
70752
|
parts.push(
|
|
69864
70753
|
util != null && util >= 0.95 ? `Withdrawals are instant in principle, but utilization is ${pct(util * 100)} \u2014 there may be little or no liquidity to withdraw right now.` : "Withdrawals are instant, up to the liquidity available in the market."
|
|
@@ -70991,7 +71880,7 @@ function finalizeInfo(sheet) {
|
|
|
70991
71880
|
sheet.borrow.info = { headline: "", description: "", tags: [] };
|
|
70992
71881
|
if (sheet.supply) {
|
|
70993
71882
|
sheet.supply.info = {
|
|
70994
|
-
headline: sheet.supply.info.headline || supplyHeadline(sheet.supply),
|
|
71883
|
+
headline: sheet.supply.info.headline || supplyHeadline(sheet.supply, sheet),
|
|
70995
71884
|
description: sheet.supply.info.description || supplyDescription(sheet.supply, sheet),
|
|
70996
71885
|
implications: sheet.supply.info.implications,
|
|
70997
71886
|
tags: deriveSupplyTags(sheet.supply, market)
|
|
@@ -71495,6 +72384,10 @@ function resolveExitMode(input, t) {
|
|
|
71495
72384
|
if (totalAssets <= 0) return "instant";
|
|
71496
72385
|
return liquidity >= totalAssets ? "instant" : "instant-capped";
|
|
71497
72386
|
}
|
|
72387
|
+
var TWO_LEGGED_MODES = /* @__PURE__ */ new Set([
|
|
72388
|
+
"fee-or-queued",
|
|
72389
|
+
"instant-or-queued"
|
|
72390
|
+
]);
|
|
71498
72391
|
var ASYNC_MODES = /* @__PURE__ */ new Set([
|
|
71499
72392
|
"fixed-cooldown",
|
|
71500
72393
|
"queued",
|
|
@@ -71508,12 +72401,29 @@ function settlementFor(mode, priceRisk) {
|
|
|
71508
72401
|
return "market";
|
|
71509
72402
|
return ASYNC_MODES.has(mode) ? "async" : "sync";
|
|
71510
72403
|
}
|
|
72404
|
+
function derivedRoutes(input, mode) {
|
|
72405
|
+
const routes2 = deriveExitRoutes({
|
|
72406
|
+
withdrawalMode: mode,
|
|
72407
|
+
withdrawFeeBps: input.withdrawFeeBps,
|
|
72408
|
+
withdrawalCooldownSeconds: input.withdrawalCooldownSeconds,
|
|
72409
|
+
liquidity: isNum2(input.liquidity) ? String(input.liquidity) : void 0,
|
|
72410
|
+
liquidityFormatted: input.liquidity,
|
|
72411
|
+
liquidityUsd: input.liquidityUsd
|
|
72412
|
+
});
|
|
72413
|
+
return routes2.length > 0 ? routes2 : void 0;
|
|
72414
|
+
}
|
|
71511
72415
|
function buildExit(input, t, fees) {
|
|
71512
72416
|
const mode = resolveExitMode(input, t);
|
|
71513
72417
|
const priceRisk = resolvePriceRisk(input, t);
|
|
71514
72418
|
const ratio = input.instantLiquidityRatio ?? (isNum2(input.liquidity) && isNum2(input.totalAssets) && input.totalAssets > 0 ? clamp014(input.liquidity / input.totalAssets) : void 0);
|
|
71515
72419
|
return {
|
|
71516
72420
|
mode,
|
|
72421
|
+
// The row's own list wins — providers that read their protocol's exit
|
|
72422
|
+
// modules attach live per-leg fees and minimums. Otherwise derive the
|
|
72423
|
+
// same split from the flat fields, because the alternative is a sheet
|
|
72424
|
+
// that states one wait and one fee belonging to DIFFERENT legs. Only a
|
|
72425
|
+
// row whose mode we cannot map at all ends up with no routes.
|
|
72426
|
+
routes: input.exitRoutes ?? derivedRoutes(input, mode),
|
|
71517
72427
|
settlement: settlementFor(mode, priceRisk),
|
|
71518
72428
|
cooldownSecs: input.withdrawalCooldownSeconds,
|
|
71519
72429
|
liquidity: isNum2(input.liquidity) || isNum2(input.liquidityUsd) ? {
|
|
@@ -71720,6 +72630,10 @@ function buildCoverage2(sheet, input, t) {
|
|
|
71720
72630
|
else pending.counterparty = "solvency-not-curated-default-assumed";
|
|
71721
72631
|
if (sheet.supply?.exit.liquidity) present.push("exitLiquidity");
|
|
71722
72632
|
else pending.exitLiquidity = "provider-does-not-publish-liquidity";
|
|
72633
|
+
if (sheet.supply?.exit.routes?.length) present.push("exitRoutes");
|
|
72634
|
+
else if (TWO_LEGGED_MODES.has(String(sheet.supply?.exit.mode)))
|
|
72635
|
+
pending.exitRoutes = "provider-does-not-publish-per-leg-terms";
|
|
72636
|
+
else notApplicable.exitRoutes = "single-exit-route";
|
|
71723
72637
|
return {
|
|
71724
72638
|
present,
|
|
71725
72639
|
notApplicable: Object.keys(notApplicable).length ? notApplicable : void 0,
|
|
@@ -72448,13 +73362,13 @@ function earnMarketFromVault(row, chainId, opts = {}) {
|
|
|
72448
73362
|
// The vault origin reports RAW base units + a pre-formatted convenience
|
|
72449
73363
|
// field. Carry both; fall back to formatting the raw amount ourselves so
|
|
72450
73364
|
// `formatted` — the field consumers sort on — is never silently absent.
|
|
72451
|
-
tvl:
|
|
73365
|
+
tvl: amount2(
|
|
72452
73366
|
tvl.totalAssets,
|
|
72453
73367
|
tvl.totalAssetsFormatted,
|
|
72454
73368
|
tvl.totalAssetsUsd,
|
|
72455
73369
|
assetDecimals
|
|
72456
73370
|
),
|
|
72457
|
-
liquidity: liq.liquidity != null || liq.liquidityUsd != null ?
|
|
73371
|
+
liquidity: liq.liquidity != null || liq.liquidityUsd != null ? amount2(
|
|
72458
73372
|
liq.liquidity,
|
|
72459
73373
|
liq.liquidityFormatted,
|
|
72460
73374
|
liq.liquidityUsd,
|
|
@@ -72466,7 +73380,10 @@ function earnMarketFromVault(row, chainId, opts = {}) {
|
|
|
72466
73380
|
mode: exitMode,
|
|
72467
73381
|
settlement: str6(meta.redemptionType),
|
|
72468
73382
|
cooldownSecs: num13(meta.withdrawalCooldownSeconds),
|
|
72469
|
-
feeBps: num13(meta.withdrawFeeBps)
|
|
73383
|
+
feeBps: num13(meta.withdrawFeeBps),
|
|
73384
|
+
// Passed through, never re-derived: the earn row and the vault row must
|
|
73385
|
+
// not disagree about what the legs out are.
|
|
73386
|
+
routes: Array.isArray(meta.exitRoutes) ? meta.exitRoutes : void 0
|
|
72470
73387
|
},
|
|
72471
73388
|
availability,
|
|
72472
73389
|
risk: {
|
|
@@ -72567,7 +73484,7 @@ function isMatured(maturity) {
|
|
|
72567
73484
|
if (!maturity?.maturity) return false;
|
|
72568
73485
|
return maturity.maturity <= Math.floor(Date.now() / 1e3);
|
|
72569
73486
|
}
|
|
72570
|
-
function
|
|
73487
|
+
function amount2(raw, formatted, usd, decimals) {
|
|
72571
73488
|
const rawStr = raw != null ? String(raw) : void 0;
|
|
72572
73489
|
return {
|
|
72573
73490
|
raw: rawStr,
|
|
@@ -72595,6 +73512,13 @@ var num14 = (v) => {
|
|
|
72595
73512
|
};
|
|
72596
73513
|
var str7 = (v) => typeof v === "string" && v.trim() !== "" ? v : void 0;
|
|
72597
73514
|
var bool2 = (v) => typeof v === "boolean" ? v : void 0;
|
|
73515
|
+
var routes = (v) => {
|
|
73516
|
+
if (!Array.isArray(v)) return void 0;
|
|
73517
|
+
const out = v.filter(
|
|
73518
|
+
(r) => !!r && typeof r === "object" && typeof r.id === "string" && typeof r.kind === "string"
|
|
73519
|
+
);
|
|
73520
|
+
return out.length > 0 ? out : void 0;
|
|
73521
|
+
};
|
|
72598
73522
|
var strArray = (v) => {
|
|
72599
73523
|
if (!Array.isArray(v)) return void 0;
|
|
72600
73524
|
const out = v.filter((x) => typeof x === "string" && x !== "");
|
|
@@ -72665,6 +73589,7 @@ function toVaultTermInput(vault, provider, chainId) {
|
|
|
72665
73589
|
withdrawalMode: str7(row.withdrawalMode),
|
|
72666
73590
|
withdrawalCooldownSeconds: num14(row.withdrawalCooldownSeconds),
|
|
72667
73591
|
withdrawFeeBps: num14(row.withdrawFeeBps),
|
|
73592
|
+
exitRoutes: routes(row.exitRoutes),
|
|
72668
73593
|
fee: num14(row.fee),
|
|
72669
73594
|
managementFee: num14(row.managementFee),
|
|
72670
73595
|
swapFeeRate: num14(row.feeRate),
|
|
@@ -72731,6 +73656,7 @@ function vaultTermInputFromEarnMarket(m) {
|
|
|
72731
73656
|
withdrawalMode: m.exit.mode,
|
|
72732
73657
|
withdrawalCooldownSeconds: m.exit.cooldownSecs,
|
|
72733
73658
|
withdrawFeeBps: m.exit.feeBps,
|
|
73659
|
+
exitRoutes: routes(m.exit.routes),
|
|
72734
73660
|
fee: m.rate.fee,
|
|
72735
73661
|
managementFee: num14(meta.managementFee),
|
|
72736
73662
|
swapFeeRate: num14(meta.feeRate),
|
|
@@ -72813,6 +73739,7 @@ function vaultTermInputFromSourceRow(row, chainId) {
|
|
|
72813
73739
|
withdrawalMode: str7(meta.withdrawalMode),
|
|
72814
73740
|
withdrawalCooldownSeconds: num14(meta.withdrawalCooldownSeconds),
|
|
72815
73741
|
withdrawFeeBps: num14(meta.withdrawFeeBps),
|
|
73742
|
+
exitRoutes: routes(meta.exitRoutes),
|
|
72816
73743
|
fee: num14(rates.fee),
|
|
72817
73744
|
managementFee: num14(meta.managementFee),
|
|
72818
73745
|
swapFeeRate: num14(meta.feeRate),
|
|
@@ -76063,11 +76990,11 @@ function earnMarketFromPool(row, fallbackChainId, venueCollaterals) {
|
|
|
76063
76990
|
// so `formatted` is populated and `raw` is genuinely absent. Do NOT
|
|
76064
76991
|
// back-fill `raw` by re-scaling — the round-trip loses precision and would
|
|
76065
76992
|
// fabricate base units the origin never sent.
|
|
76066
|
-
tvl:
|
|
76993
|
+
tvl: amount3(
|
|
76067
76994
|
row.totalDeposits,
|
|
76068
76995
|
row.totalDepositsUSD ?? row.totalDepositsUsd
|
|
76069
76996
|
),
|
|
76070
|
-
liquidity:
|
|
76997
|
+
liquidity: amount3(
|
|
76071
76998
|
row.totalLiquidity,
|
|
76072
76999
|
row.totalLiquidityUSD ?? row.totalLiquidityUsd
|
|
76073
77000
|
),
|
|
@@ -76167,7 +77094,7 @@ function sumRewardAprs(rewards) {
|
|
|
76167
77094
|
}
|
|
76168
77095
|
return seen ? total : void 0;
|
|
76169
77096
|
}
|
|
76170
|
-
function
|
|
77097
|
+
function amount3(formatted, usd) {
|
|
76171
77098
|
return { formatted: num13(formatted), usd: num13(usd) };
|
|
76172
77099
|
}
|
|
76173
77100
|
function sum2(...parts) {
|