@1delta/margin-fetcher 5.0.11 → 5.0.13
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 +194 -11
- package/dist/index.js +613 -94
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -23006,6 +23006,12 @@ var bandGrid = (m) => {
|
|
|
23006
23006
|
const set = /* @__PURE__ */ new Set([...BANDS_ENDPOINTS, bandsFor(m)]);
|
|
23007
23007
|
return [...set].sort((a, b) => a - b);
|
|
23008
23008
|
};
|
|
23009
|
+
var MIN_BANDS = 4;
|
|
23010
|
+
var MAX_BANDS = 50;
|
|
23011
|
+
var LTV_CURVE_BANDS = Array.from(
|
|
23012
|
+
{ length: MAX_BANDS - MIN_BANDS + 1 },
|
|
23013
|
+
(_3, i) => MIN_BANDS + i
|
|
23014
|
+
);
|
|
23009
23015
|
var maxBorrowableCall = (m, oneUnit, n) => m.version === 1 ? {
|
|
23010
23016
|
address: m.controller,
|
|
23011
23017
|
name: "max_borrowable",
|
|
@@ -23025,7 +23031,8 @@ var buildBandLtv = (market) => {
|
|
|
23025
23031
|
// negligible at any realistic position size and converges as it grows.
|
|
23026
23032
|
collateral: 10n ** BigInt(market.collateralDecimals + 3),
|
|
23027
23033
|
collateralDecimals: market.collateralDecimals,
|
|
23028
|
-
|
|
23034
|
+
// The FULL domain, not the multicall grid — see `LTV_CURVE_BANDS`.
|
|
23035
|
+
bandCounts: LTV_CURVE_BANDS
|
|
23029
23036
|
});
|
|
23030
23037
|
return Object.keys(curve).length > 0 ? curve : null;
|
|
23031
23038
|
} catch {
|
|
@@ -24326,7 +24333,19 @@ function convertLlamaLendMarketsToResponse(raw, chainId, prices = {}, additional
|
|
|
24326
24333
|
// this as a number gets NaN and can branch, where "0" would silently
|
|
24327
24334
|
// become a zero LTV. The real curve is in `llamalend.bandLtv`.
|
|
24328
24335
|
lltv: ltv !== null ? String(ltv) : "",
|
|
24329
|
-
|
|
24336
|
+
/**
|
|
24337
|
+
* The AMM, deliberately — LlamaLend's price feed is `price_oracle()` on
|
|
24338
|
+
* the LLAMMA itself, so that is the only address a reader can call.
|
|
24339
|
+
*
|
|
24340
|
+
* This used to read `market.priceOracle ?? market.amm`, but
|
|
24341
|
+
* `priceOracle` was never assigned anywhere in this pipeline (the name
|
|
24342
|
+
* is used elsewhere for the price VALUE, not the contract), so the
|
|
24343
|
+
* fallback was doing all the work. Naming it directly removes the trap:
|
|
24344
|
+
* a Curve `price_oracle_contract` exposes `price()` and NOT
|
|
24345
|
+
* `price_oracle()`, so populating that field would have silently
|
|
24346
|
+
* pointed every oracle reader at an interface it cannot call.
|
|
24347
|
+
*/
|
|
24348
|
+
oracle: market.amm,
|
|
24330
24349
|
irm: market.monetaryPolicy ?? zeroAddress,
|
|
24331
24350
|
collateralAddress: collAddr,
|
|
24332
24351
|
loanAddress: loanAddr,
|
|
@@ -24382,7 +24401,6 @@ function convertLlamaLendMarketsToResponse(raw, chainId, prices = {}, additional
|
|
|
24382
24401
|
*/
|
|
24383
24402
|
amm: market.amm,
|
|
24384
24403
|
monetaryPolicy: market.monetaryPolicy,
|
|
24385
|
-
priceOracle: market.priceOracle,
|
|
24386
24404
|
/**
|
|
24387
24405
|
* Curve's deployed v1 leverage zaps and the aggregator routers
|
|
24388
24406
|
* they are hard-wired to. We route leverage through these rather
|
|
@@ -40699,6 +40717,40 @@ var fraxSavingsFetcher = {
|
|
|
40699
40717
|
}
|
|
40700
40718
|
};
|
|
40701
40719
|
|
|
40720
|
+
// src/yields/intrinsic/fetchers/binance.ts
|
|
40721
|
+
var HISTORY_URL2 = "https://www.binance.com/bapi/earn/v1/public/pos/cftoken/project/exchange-rate/history";
|
|
40722
|
+
var WBETH = "Wrapped Binance Beacon ETH::wBETH";
|
|
40723
|
+
var LLAMA_POOL = "80b8bf92-b953-4c20-98ea-c9653ef2bb98";
|
|
40724
|
+
var DAY_MS = 864e5;
|
|
40725
|
+
var LOOKBACK_MS = 14 * DAY_MS;
|
|
40726
|
+
var TIMEOUT_MS2 = 8e3;
|
|
40727
|
+
var wbethFetcher = {
|
|
40728
|
+
label: "WBETH",
|
|
40729
|
+
fetch: async () => {
|
|
40730
|
+
const now = Date.now();
|
|
40731
|
+
const url = `${HISTORY_URL2}?startTime=${now - LOOKBACK_MS}&endTime=${now}`;
|
|
40732
|
+
try {
|
|
40733
|
+
const res = await fetch(url, {
|
|
40734
|
+
method: "GET",
|
|
40735
|
+
headers: { Accept: "application/json" },
|
|
40736
|
+
signal: AbortSignal.timeout(TIMEOUT_MS2)
|
|
40737
|
+
}).then((r) => r.json());
|
|
40738
|
+
const points = res.data ?? [];
|
|
40739
|
+
if (points.length > 0) {
|
|
40740
|
+
const latest = points.reduce(
|
|
40741
|
+
(a, b) => Number(b.calcDate) > Number(a.calcDate) ? b : a
|
|
40742
|
+
);
|
|
40743
|
+
const apr = Number(latest.apr) * 100;
|
|
40744
|
+
if (Number.isFinite(apr) && apr > 0) return { [WBETH]: apr };
|
|
40745
|
+
}
|
|
40746
|
+
} catch (e) {
|
|
40747
|
+
console.log("WBETH history failed, falling back to DefiLlama", e);
|
|
40748
|
+
}
|
|
40749
|
+
const apy = await fetchDefiLlamaApy(LLAMA_POOL);
|
|
40750
|
+
return { [WBETH]: apyToAprPercent(apy) };
|
|
40751
|
+
}
|
|
40752
|
+
};
|
|
40753
|
+
|
|
40702
40754
|
// src/vaults/lst/registry.ts
|
|
40703
40755
|
var LST_REGISTRY = {
|
|
40704
40756
|
// Monad (143) — native-MON LSTs. shMON / aprMON are ERC-4626 over native
|
|
@@ -41101,6 +41153,46 @@ var LST_REGISTRY = {
|
|
|
41101
41153
|
yieldFetcher: cbethFetcher,
|
|
41102
41154
|
yieldKey: "CBETH"
|
|
41103
41155
|
},
|
|
41156
|
+
{
|
|
41157
|
+
// Binance wBETH — the *other* exchange LST, and unlike cbETH above
|
|
41158
|
+
// it is genuinely permissionless on-chain in both directions:
|
|
41159
|
+
// mint `deposit(address referral)` payable, no allowlist
|
|
41160
|
+
// redeem `requestWithdrawEth(uint256)` → the UnwrapTokenV1ETH
|
|
41161
|
+
// queue at 0x79973d557CD9dd87eb61E250cc2572c990e20196
|
|
41162
|
+
// (both simulated against mainnet — `deposit` succeeds from an
|
|
41163
|
+
// arbitrary EOA, `requestWithdrawEth` reverts only on balance).
|
|
41164
|
+
//
|
|
41165
|
+
// A FiatTokenProxy (Circle's USDC codebase) + Binance's
|
|
41166
|
+
// StakedTokenV3 mixin, so it inherits USDC-style `blacklist(address)`
|
|
41167
|
+
// and `pause()` on BOTH the token and the unwrap queue — Binance can
|
|
41168
|
+
// freeze any holder. Same trust class as USDC; that is the live risk
|
|
41169
|
+
// for anything treating wBETH as collateral.
|
|
41170
|
+
//
|
|
41171
|
+
// The `queued` exit has two teeth that a plain cooldown does not:
|
|
41172
|
+
// * the ETH owed is FROZEN at request time (`ethAmount` is stored,
|
|
41173
|
+
// not recomputed), so the position stops earning for the whole
|
|
41174
|
+
// `lockTime()` — currently 864000s / 10 days, admin-settable down
|
|
41175
|
+
// to MIN_LOCK_TIME = 172800s / 2 days. Read it live.
|
|
41176
|
+
// * a request is only auto-allocated while
|
|
41177
|
+
// `availableAllocateAmount` covers it (~3 ETH on Ethereum today);
|
|
41178
|
+
// anything larger waits for Binance's operator to `allocate()`,
|
|
41179
|
+
// with no SLA.
|
|
41180
|
+
address: "0xa2e3356610840701bdf5611a53974510ae27e2e1",
|
|
41181
|
+
underlying: "0x0000000000000000000000000000000000000000",
|
|
41182
|
+
symbol: "wBETH",
|
|
41183
|
+
brand: "Binance",
|
|
41184
|
+
decimals: 18,
|
|
41185
|
+
reader: "binanceWbeth",
|
|
41186
|
+
isErc4626: false,
|
|
41187
|
+
isRebasing: false,
|
|
41188
|
+
isMintable: true,
|
|
41189
|
+
isNativeUnderlying: true,
|
|
41190
|
+
mintContract: "0xa2e3356610840701bdf5611a53974510ae27e2e1",
|
|
41191
|
+
mintInputAsset: "native",
|
|
41192
|
+
withdrawalMode: "queued",
|
|
41193
|
+
yieldFetcher: wbethFetcher,
|
|
41194
|
+
yieldKey: "Wrapped Binance Beacon ETH::wBETH"
|
|
41195
|
+
},
|
|
41104
41196
|
{
|
|
41105
41197
|
address: "0xa43a7c62d56df036c187e1966c03e2799d8987ed",
|
|
41106
41198
|
// TruFin TruStake MATIC Vault uses the MATIC ERC-20 (not POL).
|
|
@@ -41667,6 +41759,37 @@ var LST_REGISTRY = {
|
|
|
41667
41759
|
listaStakeManager: "0x1adb950d8bb3da4be104211d5ab038628e477fe6"
|
|
41668
41760
|
}
|
|
41669
41761
|
},
|
|
41762
|
+
{
|
|
41763
|
+
// Binance wBETH on BNB — SAME token address as Ethereum, but a
|
|
41764
|
+
// different implementation behind the proxy (`WrapTokenV2BSC` vs
|
|
41765
|
+
// `WrapTokenV3ETH`), so the mint leg is NOT portable:
|
|
41766
|
+
// Ethereum `deposit(address referral)` payable, native ETH
|
|
41767
|
+
// BNB `deposit(uint256 amount, address referral)` nonpayable,
|
|
41768
|
+
// pulls the Binance-pegged ETH ERC-20 below → needs approve
|
|
41769
|
+
// The read surface and the pushed rate ARE identical (one oracle
|
|
41770
|
+
// 0x81720695… writes both chains, and `exchangeRate()` returns the
|
|
41771
|
+
// same value), hence the shared reader and the shared `yieldKey`.
|
|
41772
|
+
//
|
|
41773
|
+
// Exit is the same UnwrapTokenV1 queue at the same address, with the
|
|
41774
|
+
// same frozen-amount / 10-day-lock / operator-allocation caveats as
|
|
41775
|
+
// the Ethereum entry — see there.
|
|
41776
|
+
address: "0xa2e3356610840701bdf5611a53974510ae27e2e1",
|
|
41777
|
+
// Binance-pegged ETH on BSC — the deposit input, not native BNB.
|
|
41778
|
+
underlying: "0x2170ed0880ac9a755fd29b2688956bd959f933f8",
|
|
41779
|
+
symbol: "wBETH",
|
|
41780
|
+
brand: "Binance",
|
|
41781
|
+
decimals: 18,
|
|
41782
|
+
reader: "binanceWbeth",
|
|
41783
|
+
isErc4626: false,
|
|
41784
|
+
isRebasing: false,
|
|
41785
|
+
isMintable: true,
|
|
41786
|
+
isNativeUnderlying: false,
|
|
41787
|
+
mintContract: "0xa2e3356610840701bdf5611a53974510ae27e2e1",
|
|
41788
|
+
mintInputAsset: "0x2170ed0880ac9a755fd29b2688956bd959f933f8",
|
|
41789
|
+
withdrawalMode: "queued",
|
|
41790
|
+
yieldFetcher: wbethFetcher,
|
|
41791
|
+
yieldKey: "Wrapped Binance Beacon ETH::wBETH"
|
|
41792
|
+
},
|
|
41670
41793
|
{
|
|
41671
41794
|
// YieldNest ynBNB — ERC-4626 vault over slisBNB (Lista), restaked
|
|
41672
41795
|
// via Kernel. Redeems to slisBNB synchronously; the BNB unstake
|
|
@@ -46061,32 +46184,85 @@ var upshiftFetcher = {
|
|
|
46061
46184
|
}
|
|
46062
46185
|
};
|
|
46063
46186
|
|
|
46064
|
-
// src/
|
|
46065
|
-
var
|
|
46066
|
-
|
|
46067
|
-
"
|
|
46068
|
-
|
|
46069
|
-
"
|
|
46070
|
-
|
|
46071
|
-
|
|
46187
|
+
// src/vaults/yearn/api.ts
|
|
46188
|
+
var YEARN_YDAEMON_BASE = "https://ydaemon.yearn.fi";
|
|
46189
|
+
var YEARN_CHAIN_IDS = /* @__PURE__ */ new Set([
|
|
46190
|
+
"1",
|
|
46191
|
+
// Ethereum
|
|
46192
|
+
"137",
|
|
46193
|
+
// Polygon
|
|
46194
|
+
"8453",
|
|
46195
|
+
// Base
|
|
46196
|
+
"42161",
|
|
46197
|
+
// Arbitrum
|
|
46198
|
+
"100",
|
|
46199
|
+
// Gnosis
|
|
46200
|
+
"146",
|
|
46201
|
+
// Sonic
|
|
46202
|
+
"747474"
|
|
46203
|
+
// Katana
|
|
46204
|
+
]);
|
|
46205
|
+
var hasYearnVaults = (chainId) => YEARN_CHAIN_IDS.has(String(chainId));
|
|
46206
|
+
var isYearnV3 = (v) => typeof v?.version === "string" && v.version.startsWith("3.");
|
|
46207
|
+
var PAGE_SIZE = 2e3;
|
|
46208
|
+
async function fetchYearnApiVaults(chainId) {
|
|
46209
|
+
const out = [];
|
|
46210
|
+
const seen = /* @__PURE__ */ new Set();
|
|
46211
|
+
for (let page = 1; page <= 20; page++) {
|
|
46212
|
+
const url = `${YEARN_YDAEMON_BASE}/${chainId}/vaults/all?limit=${PAGE_SIZE}&page=${page}`;
|
|
46213
|
+
const response = await fetch(url);
|
|
46214
|
+
if (!response.ok) {
|
|
46215
|
+
throw new Error(
|
|
46216
|
+
`Yearn yDaemon API failed: ${response.status} - ${response.statusText}`
|
|
46217
|
+
);
|
|
46218
|
+
}
|
|
46219
|
+
const body = await response.text();
|
|
46220
|
+
if (!body.trim()) break;
|
|
46221
|
+
const items = JSON.parse(body);
|
|
46222
|
+
if (!Array.isArray(items)) break;
|
|
46223
|
+
for (const v of items) {
|
|
46224
|
+
const address = (v?.address ?? "").toLowerCase();
|
|
46225
|
+
if (!address || seen.has(address)) continue;
|
|
46226
|
+
if (isYearnV3(v) && v.endorsed) {
|
|
46227
|
+
seen.add(address);
|
|
46228
|
+
out.push(v);
|
|
46229
|
+
}
|
|
46230
|
+
}
|
|
46231
|
+
if (items.length < PAGE_SIZE) break;
|
|
46232
|
+
}
|
|
46233
|
+
return out;
|
|
46234
|
+
}
|
|
46072
46235
|
|
|
46073
|
-
// src/yields/intrinsic/fetchers/
|
|
46074
|
-
var
|
|
46075
|
-
var
|
|
46076
|
-
|
|
46236
|
+
// src/yields/intrinsic/fetchers/yearn.ts
|
|
46237
|
+
var toPct = (v) => typeof v === "number" && Number.isFinite(v) ? v * 100 : null;
|
|
46238
|
+
var yearnVaultApr = (v) => toPct(v.apr?.netAPR) ?? toPct(v.apr?.forwardAPR?.netAPR);
|
|
46239
|
+
var yearnFetcher = {
|
|
46240
|
+
label: "YEARN",
|
|
46077
46241
|
fetch: async () => {
|
|
46078
|
-
const
|
|
46079
|
-
|
|
46080
|
-
|
|
46081
|
-
|
|
46082
|
-
|
|
46083
|
-
|
|
46084
|
-
|
|
46085
|
-
|
|
46086
|
-
|
|
46087
|
-
|
|
46088
|
-
|
|
46089
|
-
|
|
46242
|
+
const chainIds = [...YEARN_CHAIN_IDS];
|
|
46243
|
+
const lists = await getListsMulti(chainIds);
|
|
46244
|
+
const perChain = await Promise.all(
|
|
46245
|
+
chainIds.map(async (chainId) => {
|
|
46246
|
+
const out = {};
|
|
46247
|
+
let vaults = [];
|
|
46248
|
+
try {
|
|
46249
|
+
vaults = await fetchYearnApiVaults(chainId);
|
|
46250
|
+
} catch (e) {
|
|
46251
|
+
console.error(`Error fetching YEARN vaults on chain ${chainId}:`, e);
|
|
46252
|
+
return out;
|
|
46253
|
+
}
|
|
46254
|
+
for (const v of vaults) {
|
|
46255
|
+
const address = (v.address ?? "").toLowerCase();
|
|
46256
|
+
const assetKey = lists[chainId]?.list?.[address]?.assetGroup;
|
|
46257
|
+
if (!assetKey) continue;
|
|
46258
|
+
const apr = yearnVaultApr(v);
|
|
46259
|
+
if (apr == null) continue;
|
|
46260
|
+
out[assetKey] = apr;
|
|
46261
|
+
}
|
|
46262
|
+
return out;
|
|
46263
|
+
})
|
|
46264
|
+
);
|
|
46265
|
+
return Object.assign({}, ...perChain);
|
|
46090
46266
|
}
|
|
46091
46267
|
};
|
|
46092
46268
|
|
|
@@ -46150,7 +46326,9 @@ var LENDING_ONLY_FETCHERS = [
|
|
|
46150
46326
|
nestFetcher,
|
|
46151
46327
|
accountableFetcher,
|
|
46152
46328
|
upshiftFetcher,
|
|
46153
|
-
|
|
46329
|
+
// Every endorsed Yearn V3 vault on every Yearn chain (Katana included —
|
|
46330
|
+
// it superseded the Katana-only fetcher, which double-counted).
|
|
46331
|
+
yearnFetcher,
|
|
46154
46332
|
// DefiLlama-mapped intrinsic yields for classifier assets lacking a bespoke source
|
|
46155
46333
|
lsethFetcher,
|
|
46156
46334
|
tethFetcher,
|
|
@@ -46251,6 +46429,76 @@ function extractRewardBreakdowns(opp) {
|
|
|
46251
46429
|
distributionType: b.distributionType
|
|
46252
46430
|
}));
|
|
46253
46431
|
}
|
|
46432
|
+
function unixSeconds(v) {
|
|
46433
|
+
if (v === void 0 || v === null) return void 0;
|
|
46434
|
+
const n = typeof v === "number" ? v : Number(v);
|
|
46435
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
46436
|
+
}
|
|
46437
|
+
function buildMerklStreams(opp, side, totalApr, source) {
|
|
46438
|
+
const rewardBreakdowns = opp.rewardsRecord?.breakdowns ?? [];
|
|
46439
|
+
const endsAt = unixSeconds(opp.earliestCampaignEnd ?? opp.latestCampaignEnd);
|
|
46440
|
+
const startsAt = unixSeconds(
|
|
46441
|
+
opp.earliestCampaignStart ?? opp.latestCampaignStart
|
|
46442
|
+
);
|
|
46443
|
+
const base = {
|
|
46444
|
+
side,
|
|
46445
|
+
kind: "token",
|
|
46446
|
+
claim: "merkl",
|
|
46447
|
+
endsAt,
|
|
46448
|
+
startsAt
|
|
46449
|
+
};
|
|
46450
|
+
if (!rewardBreakdowns.length) {
|
|
46451
|
+
return [{ ...base, apr: totalApr, token: void 0, source }];
|
|
46452
|
+
}
|
|
46453
|
+
const aprByCampaign = /* @__PURE__ */ new Map();
|
|
46454
|
+
for (const b of opp.aprRecord?.breakdowns ?? []) {
|
|
46455
|
+
if (b?.identifier && Number.isFinite(b.value))
|
|
46456
|
+
aprByCampaign.set(b.identifier.toLowerCase(), b.value);
|
|
46457
|
+
}
|
|
46458
|
+
const totalDaily = rewardBreakdowns.reduce((s, b) => s + (b.value || 0), 0);
|
|
46459
|
+
return rewardBreakdowns.map((b) => {
|
|
46460
|
+
const campaignApr = b.onChainCampaignId ? aprByCampaign.get(b.onChainCampaignId.toLowerCase()) : void 0;
|
|
46461
|
+
const apr = campaignApr ?? (totalDaily > 0 ? totalApr * (b.value || 0) / totalDaily : totalApr / rewardBreakdowns.length);
|
|
46462
|
+
return {
|
|
46463
|
+
...base,
|
|
46464
|
+
apr,
|
|
46465
|
+
token: {
|
|
46466
|
+
address: b.token.address.toLowerCase(),
|
|
46467
|
+
chainId: String(opp.chainId),
|
|
46468
|
+
symbol: b.token.symbol,
|
|
46469
|
+
decimals: b.token.decimals,
|
|
46470
|
+
logoURI: b.token.icon,
|
|
46471
|
+
priceUsd: b.token.price ?? void 0
|
|
46472
|
+
},
|
|
46473
|
+
dailyRewardsUsd: b.value,
|
|
46474
|
+
source: {
|
|
46475
|
+
...source,
|
|
46476
|
+
refs: {
|
|
46477
|
+
...source.refs ?? {},
|
|
46478
|
+
...b.onChainCampaignId ? { onChainCampaignId: b.onChainCampaignId } : {},
|
|
46479
|
+
...b.campaignId ? { campaignId: b.campaignId } : {},
|
|
46480
|
+
...b.distributionType ? { distributionType: b.distributionType } : {}
|
|
46481
|
+
}
|
|
46482
|
+
}
|
|
46483
|
+
};
|
|
46484
|
+
});
|
|
46485
|
+
}
|
|
46486
|
+
function merklSourceRef(opp, merklProtocolId) {
|
|
46487
|
+
const protocolName = opp.protocol?.name ?? merklProtocolId;
|
|
46488
|
+
return {
|
|
46489
|
+
id: `merkl:${merklProtocolId}`,
|
|
46490
|
+
label: `Merkl \xB7 ${protocolName}`,
|
|
46491
|
+
link: getMerkleUrl(opp),
|
|
46492
|
+
platform: "merkl",
|
|
46493
|
+
refs: {
|
|
46494
|
+
opportunityId: opp.identifier,
|
|
46495
|
+
opportunityType: opp.type,
|
|
46496
|
+
chain: opp.chain?.name ?? String(opp.chainId),
|
|
46497
|
+
...opp.name ? { opportunityName: opp.name } : {},
|
|
46498
|
+
...opp.liveCampaigns ? { liveCampaigns: opp.liveCampaigns } : {}
|
|
46499
|
+
}
|
|
46500
|
+
};
|
|
46501
|
+
}
|
|
46254
46502
|
function resolveUnderlyingFromOpportunity(opp) {
|
|
46255
46503
|
if (!opp.tokens?.length) return void 0;
|
|
46256
46504
|
if (opp.depositUrl) {
|
|
@@ -46316,6 +46564,11 @@ function createMerklRewardFetcher(config) {
|
|
|
46316
46564
|
);
|
|
46317
46565
|
const breakdowns = extractRewardBreakdowns(opp);
|
|
46318
46566
|
reward.link = getMerkleUrl(opp);
|
|
46567
|
+
const source = merklSourceRef(opp, config.merklProtocolId);
|
|
46568
|
+
if (!reward.streams) reward.streams = [];
|
|
46569
|
+
reward.streams.push(
|
|
46570
|
+
...buildMerklStreams(opp, bucket, opp.apr, source)
|
|
46571
|
+
);
|
|
46319
46572
|
if (bucket === "deposit") {
|
|
46320
46573
|
reward.deposit += opp.apr;
|
|
46321
46574
|
reward.additionalDepositData.push(...breakdowns);
|
|
@@ -46520,8 +46773,21 @@ var ABI = [
|
|
|
46520
46773
|
stateMutability: "view",
|
|
46521
46774
|
inputs: [],
|
|
46522
46775
|
outputs: [{ type: "uint8" }]
|
|
46776
|
+
},
|
|
46777
|
+
{
|
|
46778
|
+
name: "symbol",
|
|
46779
|
+
type: "function",
|
|
46780
|
+
stateMutability: "view",
|
|
46781
|
+
inputs: [],
|
|
46782
|
+
outputs: [{ type: "string" }]
|
|
46523
46783
|
}
|
|
46524
46784
|
];
|
|
46785
|
+
var DTRINITY_SOURCE = {
|
|
46786
|
+
id: "dtrinity:rebate",
|
|
46787
|
+
label: "dTRINITY borrow rebate",
|
|
46788
|
+
link: "https://docs.dtrinity.org/protocol-components/dlend",
|
|
46789
|
+
platform: "protocol"
|
|
46790
|
+
};
|
|
46525
46791
|
var isZero = (a) => !a || a.toLowerCase() === ZERO_ADDRESS5;
|
|
46526
46792
|
var scale = (raw, decimals) => Number(raw) / 10 ** decimals;
|
|
46527
46793
|
function emptyReward2() {
|
|
@@ -46635,19 +46901,25 @@ async function fetchForPool(chainId, lender, pool, nowSeconds) {
|
|
|
46635
46901
|
calls: pairs.flatMap((p) => [
|
|
46636
46902
|
call(p.leg.controller, "getRewardsData", [p.leg.balanceToken, p.reward]),
|
|
46637
46903
|
call(p.reward, "decimals"),
|
|
46638
|
-
call(oracle, "getAssetPrice", [p.reward])
|
|
46904
|
+
call(oracle, "getAssetPrice", [p.reward]),
|
|
46905
|
+
call(p.reward, "symbol")
|
|
46639
46906
|
]),
|
|
46640
46907
|
allowFailure: false
|
|
46641
46908
|
});
|
|
46909
|
+
const STRIDE = 4;
|
|
46642
46910
|
const result = {};
|
|
46643
46911
|
pairs.forEach((p, i) => {
|
|
46644
|
-
const data = round5[i *
|
|
46912
|
+
const data = round5[i * STRIDE];
|
|
46645
46913
|
if (!data) return;
|
|
46914
|
+
const rewardDecimals = Number(round5[i * STRIDE + 1] ?? 18);
|
|
46915
|
+
const rewardPrice = Number(round5[i * STRIDE + 2] ?? 0n);
|
|
46916
|
+
const rewardSymbol = round5[i * STRIDE + 3];
|
|
46917
|
+
const distributionEnd = Number(data[3] ?? 0);
|
|
46646
46918
|
const apr = rebateApr({
|
|
46647
46919
|
emissionPerSecond: BigInt(data[1] ?? 0),
|
|
46648
46920
|
distributionEnd: BigInt(data[3] ?? 0),
|
|
46649
|
-
rewardDecimals
|
|
46650
|
-
rewardPrice
|
|
46921
|
+
rewardDecimals,
|
|
46922
|
+
rewardPrice,
|
|
46651
46923
|
balanceTotalSupply: BigInt(p.leg.totalSupply ?? 0),
|
|
46652
46924
|
balanceDecimals: p.leg.decimals,
|
|
46653
46925
|
assetPrice: priceByAsset[p.leg.asset] ?? 0,
|
|
@@ -46662,9 +46934,34 @@ async function fetchForPool(chainId, lender, pool, nowSeconds) {
|
|
|
46662
46934
|
const breakdown = {
|
|
46663
46935
|
tokenAddress: p.reward.toLowerCase(),
|
|
46664
46936
|
emissionPerSecond: String(data[1]),
|
|
46665
|
-
distributionEnd
|
|
46937
|
+
distributionEnd,
|
|
46666
46938
|
distributionType: "aave-incentives"
|
|
46667
46939
|
};
|
|
46940
|
+
if (!entry.streams) entry.streams = [];
|
|
46941
|
+
entry.streams.push({
|
|
46942
|
+
side: p.leg.bucket,
|
|
46943
|
+
apr,
|
|
46944
|
+
kind: "token",
|
|
46945
|
+
token: {
|
|
46946
|
+
address: p.reward.toLowerCase(),
|
|
46947
|
+
chainId,
|
|
46948
|
+
symbol: rewardSymbol,
|
|
46949
|
+
decimals: rewardDecimals,
|
|
46950
|
+
// The pool's AaveOracle is 1e8-based on every dLEND deployment.
|
|
46951
|
+
priceUsd: rewardPrice > 0 ? rewardPrice / 1e8 : void 0
|
|
46952
|
+
},
|
|
46953
|
+
source: {
|
|
46954
|
+
...DTRINITY_SOURCE,
|
|
46955
|
+
refs: {
|
|
46956
|
+
incentivesController: p.leg.controller.toLowerCase(),
|
|
46957
|
+
balanceToken: p.leg.balanceToken.toLowerCase(),
|
|
46958
|
+
emissionPerSecond: String(data[1])
|
|
46959
|
+
}
|
|
46960
|
+
},
|
|
46961
|
+
claim: "accrual",
|
|
46962
|
+
endsAt: distributionEnd > 0 ? distributionEnd : void 0,
|
|
46963
|
+
dailyRewardsUsd: rewardPrice > 0 ? Number(data[1] ?? 0) / 10 ** rewardDecimals * 86400 * (rewardPrice / 1e8) : void 0
|
|
46964
|
+
});
|
|
46668
46965
|
if (p.leg.bucket === "deposit") {
|
|
46669
46966
|
entry.deposit += apr;
|
|
46670
46967
|
entry.additionalDepositData.push(breakdown);
|
|
@@ -48220,6 +48517,79 @@ var listaFetcher = {
|
|
|
48220
48517
|
parse: parseListaResults,
|
|
48221
48518
|
getAbi: getListaAbi
|
|
48222
48519
|
};
|
|
48520
|
+
function generateLlamaLendLenderKey(marketId) {
|
|
48521
|
+
return `${Lender.LLAMALEND}_${marketId.replace(/^0x/i, "").toUpperCase()}`;
|
|
48522
|
+
}
|
|
48523
|
+
function getLlamaLendMarketsForChain(chainId, marketOverrides) {
|
|
48524
|
+
return marketOverrides?.[chainId] ?? [];
|
|
48525
|
+
}
|
|
48526
|
+
function getLlamaLendCalls(chainId, context) {
|
|
48527
|
+
const markets = getLlamaLendMarketsForChain(chainId, context?.marketOverrides);
|
|
48528
|
+
if (markets.length === 0) return [];
|
|
48529
|
+
return markets.map((market) => {
|
|
48530
|
+
const call = {
|
|
48531
|
+
address: market.amm,
|
|
48532
|
+
name: "price_oracle",
|
|
48533
|
+
params: []
|
|
48534
|
+
};
|
|
48535
|
+
return {
|
|
48536
|
+
calls: [call],
|
|
48537
|
+
meta: { markets: [market] },
|
|
48538
|
+
lender: generateLlamaLendLenderKey(market.marketId)
|
|
48539
|
+
};
|
|
48540
|
+
});
|
|
48541
|
+
}
|
|
48542
|
+
function parseLlamaLendResults(data, meta, context) {
|
|
48543
|
+
const { chainId, usdPrices, tokenList } = context;
|
|
48544
|
+
const entries = [];
|
|
48545
|
+
const rawPrice = data[0];
|
|
48546
|
+
if (rawPrice === void 0 || rawPrice === null || rawPrice === "0x") {
|
|
48547
|
+
return entries;
|
|
48548
|
+
}
|
|
48549
|
+
for (const market of meta.markets) {
|
|
48550
|
+
const loanAsset = market.loanAsset.toLowerCase();
|
|
48551
|
+
const collateralAsset = market.collateralAsset.toLowerCase();
|
|
48552
|
+
let collateralInLoan;
|
|
48553
|
+
try {
|
|
48554
|
+
collateralInLoan = Number(formatUnits(BigInt(rawPrice.toString()), 18));
|
|
48555
|
+
} catch {
|
|
48556
|
+
continue;
|
|
48557
|
+
}
|
|
48558
|
+
if (!Number.isFinite(collateralInLoan) || collateralInLoan === 0) continue;
|
|
48559
|
+
const loanOracleKey = tokenList?.[loanAsset]?.assetGroup ?? `${chainId}-${loanAsset}`;
|
|
48560
|
+
const loanAssetUSD = usdPrices[loanOracleKey] ?? usdPrices[loanAsset];
|
|
48561
|
+
if (!loanAssetUSD) continue;
|
|
48562
|
+
const lenderKey = generateLlamaLendLenderKey(market.marketId);
|
|
48563
|
+
entries.push({
|
|
48564
|
+
asset: loanAsset,
|
|
48565
|
+
price: 1,
|
|
48566
|
+
priceUSD: loanAssetUSD,
|
|
48567
|
+
marketUid: createMarketUid(chainId, lenderKey, loanAsset),
|
|
48568
|
+
targetLender: lenderKey,
|
|
48569
|
+
description: "LlamaLend borrowed asset",
|
|
48570
|
+
staticBase: true,
|
|
48571
|
+
baseAsset: loanAsset
|
|
48572
|
+
});
|
|
48573
|
+
entries.push({
|
|
48574
|
+
asset: collateralAsset,
|
|
48575
|
+
price: collateralInLoan,
|
|
48576
|
+
priceUSD: collateralInLoan * loanAssetUSD,
|
|
48577
|
+
marketUid: createMarketUid(chainId, lenderKey, collateralAsset),
|
|
48578
|
+
targetLender: lenderKey,
|
|
48579
|
+
description: "LlamaLend collateral (AMM EMA oracle)",
|
|
48580
|
+
baseAsset: loanAsset
|
|
48581
|
+
});
|
|
48582
|
+
}
|
|
48583
|
+
return entries;
|
|
48584
|
+
}
|
|
48585
|
+
function getLlamaLendAbi() {
|
|
48586
|
+
return LlamaLendAmmAbi;
|
|
48587
|
+
}
|
|
48588
|
+
var llamaLendFetcher = {
|
|
48589
|
+
getCalls: getLlamaLendCalls,
|
|
48590
|
+
parse: parseLlamaLendResults,
|
|
48591
|
+
getAbi: getLlamaLendAbi
|
|
48592
|
+
};
|
|
48223
48593
|
|
|
48224
48594
|
// src/abis/euler/priceLens.ts
|
|
48225
48595
|
var priceLensAbi = [
|
|
@@ -49580,7 +49950,7 @@ async function executeGroup(group, chainId, chainBatchSize, retries, allowFailur
|
|
|
49580
49950
|
};
|
|
49581
49951
|
}
|
|
49582
49952
|
}
|
|
49583
|
-
async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers, probeFeedStaleness = true) {
|
|
49953
|
+
async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3, batchSize = void 0, allowFailure = true, basePrices = {}, morphoMarketOverrides, listaMarketOverrides, stalenessThresholdSeconds = 3600, onlyFetchers, probeFeedStaleness = true, llamaLendMarketOverrides) {
|
|
49584
49954
|
const totalStart = Date.now();
|
|
49585
49955
|
const result = {};
|
|
49586
49956
|
const chainPromises = chainIds.map(async (chainId) => {
|
|
@@ -49625,6 +49995,13 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
|
|
|
49625
49995
|
}),
|
|
49626
49996
|
getCallsErrors
|
|
49627
49997
|
) : [];
|
|
49998
|
+
const llamaLendResults = isActive("llamalend") ? safeGetCalls(
|
|
49999
|
+
"llamaLend",
|
|
50000
|
+
() => llamaLendFetcher.getCalls(chainId, {
|
|
50001
|
+
marketOverrides: llamaLendMarketOverrides
|
|
50002
|
+
}),
|
|
50003
|
+
getCallsErrors
|
|
50004
|
+
) : [];
|
|
49628
50005
|
const eulerResults = isActive("eulerv2") ? safeGetCalls(
|
|
49629
50006
|
"eulerV2",
|
|
49630
50007
|
() => eulerV2Fetcher.getCalls(chainId),
|
|
@@ -49745,6 +50122,13 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
|
|
|
49745
50122
|
ProxyOracleAbi,
|
|
49746
50123
|
"direct"
|
|
49747
50124
|
);
|
|
50125
|
+
const llamaLendGroup = buildGroup(
|
|
50126
|
+
"llamaLend",
|
|
50127
|
+
llamaLendResults,
|
|
50128
|
+
llamaLendFetcher.parse,
|
|
50129
|
+
getLlamaLendAbi(),
|
|
50130
|
+
"derived"
|
|
50131
|
+
);
|
|
49748
50132
|
const eulerGroup = buildGroup(
|
|
49749
50133
|
"eulerV2",
|
|
49750
50134
|
eulerResults,
|
|
@@ -49871,6 +50255,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
|
|
|
49871
50255
|
compoundV2Group,
|
|
49872
50256
|
compoundV3Group,
|
|
49873
50257
|
listaGroup,
|
|
50258
|
+
llamaLendGroup,
|
|
49874
50259
|
eulerGroup,
|
|
49875
50260
|
aaveV4Group,
|
|
49876
50261
|
morphoGroup,
|
|
@@ -49918,6 +50303,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
|
|
|
49918
50303
|
compoundV2Data,
|
|
49919
50304
|
compoundV3Data,
|
|
49920
50305
|
listaData,
|
|
50306
|
+
llamaLendData,
|
|
49921
50307
|
eulerData,
|
|
49922
50308
|
aaveV4Data,
|
|
49923
50309
|
fluidData,
|
|
@@ -49968,6 +50354,14 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
|
|
|
49968
50354
|
allowFailure,
|
|
49969
50355
|
rpcOverrides
|
|
49970
50356
|
),
|
|
50357
|
+
executeGroup(
|
|
50358
|
+
llamaLendGroup,
|
|
50359
|
+
chainId,
|
|
50360
|
+
chainBatchSize,
|
|
50361
|
+
retries,
|
|
50362
|
+
allowFailure,
|
|
50363
|
+
rpcOverrides
|
|
50364
|
+
),
|
|
49971
50365
|
executeGroup(
|
|
49972
50366
|
eulerGroup,
|
|
49973
50367
|
chainId,
|
|
@@ -50125,6 +50519,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
|
|
|
50125
50519
|
{ group: compoundV2Group, data: compoundV2Data },
|
|
50126
50520
|
{ group: compoundV3Group, data: compoundV3Data },
|
|
50127
50521
|
{ group: listaGroup, data: listaData },
|
|
50522
|
+
{ group: llamaLendGroup, data: llamaLendData },
|
|
50128
50523
|
{ group: eulerGroup, data: eulerData },
|
|
50129
50524
|
{ group: aaveV4Group, data: aaveV4Data },
|
|
50130
50525
|
{ group: fluidGroup, data: fluidData },
|
|
@@ -50317,6 +50712,7 @@ async function fetchOraclePrices(chainIds, rpcOverrides, lists = {}, retries = 3
|
|
|
50317
50712
|
}
|
|
50318
50713
|
parseTrackers(midnightGroup, midnightData.results, false);
|
|
50319
50714
|
parseTrackers(tellerGroup, tellerData.results, false);
|
|
50715
|
+
parseTrackers(llamaLendGroup, llamaLendData.results, false);
|
|
50320
50716
|
if (stalenessThresholdSeconds > 0) {
|
|
50321
50717
|
const feedTimestamps = await feedTimestampsPromise;
|
|
50322
50718
|
for (const [lender, assetMap] of Object.entries(feedTimestamps)) {
|
|
@@ -51506,7 +51902,7 @@ var fetchGearboxV3Pools = async (chainId, multicallRetry, prices = {}, tokenList
|
|
|
51506
51902
|
// src/vaults/morpho/fetchFromApi.ts
|
|
51507
51903
|
var MORPHO_SHARE_DECIMALS = 18;
|
|
51508
51904
|
var MORPHO_API_URL = "https://blue-api.morpho.org/graphql";
|
|
51509
|
-
var
|
|
51905
|
+
var PAGE_SIZE2 = 200;
|
|
51510
51906
|
var vaultsQuery = (first, skip, chainId) => `
|
|
51511
51907
|
query GetVaults {
|
|
51512
51908
|
vaults(
|
|
@@ -51671,14 +52067,14 @@ async function fetchMorphoVaultsFromApi(chainId, prices = {}, tokenList = {}, ma
|
|
|
51671
52067
|
const out = {};
|
|
51672
52068
|
let skip = 0;
|
|
51673
52069
|
while (skip < maxItems) {
|
|
51674
|
-
const page = await fetchPage(chainId,
|
|
52070
|
+
const page = await fetchPage(chainId, PAGE_SIZE2, skip);
|
|
51675
52071
|
if (page.length === 0) break;
|
|
51676
52072
|
for (const v of page) {
|
|
51677
52073
|
const parsed = parseVault2(v, chainId, prices, tokenList);
|
|
51678
52074
|
if (parsed) out[parsed.address] = parsed;
|
|
51679
52075
|
}
|
|
51680
|
-
if (page.length <
|
|
51681
|
-
skip +=
|
|
52076
|
+
if (page.length < PAGE_SIZE2) break;
|
|
52077
|
+
skip += PAGE_SIZE2;
|
|
51682
52078
|
}
|
|
51683
52079
|
return out;
|
|
51684
52080
|
}
|
|
@@ -54808,6 +55204,38 @@ var readerAnkrRatio = (entry) => ({
|
|
|
54808
55204
|
}
|
|
54809
55205
|
});
|
|
54810
55206
|
|
|
55207
|
+
// src/vaults/lst/abis/binance.ts
|
|
55208
|
+
var WbethExchangeRateAbi = [
|
|
55209
|
+
{
|
|
55210
|
+
name: "exchangeRate",
|
|
55211
|
+
type: "function",
|
|
55212
|
+
stateMutability: "view",
|
|
55213
|
+
inputs: [],
|
|
55214
|
+
outputs: [{ type: "uint256" }]
|
|
55215
|
+
}
|
|
55216
|
+
];
|
|
55217
|
+
|
|
55218
|
+
// src/vaults/lst/readers/binance.ts
|
|
55219
|
+
var readerBinanceWbeth = (entry) => ({
|
|
55220
|
+
calls: [
|
|
55221
|
+
{ address: entry.address, name: "totalSupply", params: [] },
|
|
55222
|
+
{ address: entry.address, name: "exchangeRate", params: [] }
|
|
55223
|
+
],
|
|
55224
|
+
abis: [TotalSupplyAbi, WbethExchangeRateAbi],
|
|
55225
|
+
parse: ([supply, rate]) => {
|
|
55226
|
+
const totalSupply = toBigInt13(supply);
|
|
55227
|
+
const exchangeRate = toBigInt13(rate);
|
|
55228
|
+
if (totalSupply === void 0 || exchangeRate === void 0) {
|
|
55229
|
+
return void 0;
|
|
55230
|
+
}
|
|
55231
|
+
return {
|
|
55232
|
+
totalAssets: totalSupply * exchangeRate / ONE_E189,
|
|
55233
|
+
totalSupply,
|
|
55234
|
+
exchangeRate
|
|
55235
|
+
};
|
|
55236
|
+
}
|
|
55237
|
+
});
|
|
55238
|
+
|
|
54811
55239
|
// src/vaults/lst/abis/core.ts
|
|
54812
55240
|
var CoreEarnRateAbi = [
|
|
54813
55241
|
{
|
|
@@ -54930,6 +55358,8 @@ var buildReader = (entry) => {
|
|
|
54930
55358
|
return readerKelpRsEth(entry);
|
|
54931
55359
|
case "swellGetRate":
|
|
54932
55360
|
return readerSwellGetRate(entry);
|
|
55361
|
+
case "binanceWbeth":
|
|
55362
|
+
return readerBinanceWbeth(entry);
|
|
54933
55363
|
case "stakewiseOsEth":
|
|
54934
55364
|
return readerStakeWiseOsEth(entry);
|
|
54935
55365
|
case "staderEthx":
|
|
@@ -55827,6 +56257,96 @@ var readerBenqi = {
|
|
|
55827
56257
|
}
|
|
55828
56258
|
};
|
|
55829
56259
|
|
|
56260
|
+
// src/vaults/lst/withdrawals/abis/binance.ts
|
|
56261
|
+
var BinanceUnwrapQueueAbi = [
|
|
56262
|
+
{
|
|
56263
|
+
name: "getUserWithdrawRequests",
|
|
56264
|
+
type: "function",
|
|
56265
|
+
stateMutability: "view",
|
|
56266
|
+
inputs: [{ type: "address", name: "recipient" }],
|
|
56267
|
+
outputs: [
|
|
56268
|
+
{
|
|
56269
|
+
type: "tuple[]",
|
|
56270
|
+
components: [
|
|
56271
|
+
{ type: "address", name: "recipient" },
|
|
56272
|
+
{ type: "uint256", name: "wbethAmount" },
|
|
56273
|
+
{ type: "uint256", name: "ethAmount" },
|
|
56274
|
+
{ type: "uint256", name: "triggerTime" },
|
|
56275
|
+
{ type: "uint256", name: "claimTime" },
|
|
56276
|
+
{ type: "bool", name: "allocated" }
|
|
56277
|
+
]
|
|
56278
|
+
}
|
|
56279
|
+
]
|
|
56280
|
+
},
|
|
56281
|
+
{
|
|
56282
|
+
// Currently 864000 (10 days). Admin-settable down to
|
|
56283
|
+
// `MIN_LOCK_TIME` = 172800 (2 days) — always read it, never hardcode.
|
|
56284
|
+
name: "lockTime",
|
|
56285
|
+
type: "function",
|
|
56286
|
+
stateMutability: "view",
|
|
56287
|
+
inputs: [],
|
|
56288
|
+
outputs: [{ type: "uint256" }]
|
|
56289
|
+
},
|
|
56290
|
+
{
|
|
56291
|
+
name: "claimWithdraw",
|
|
56292
|
+
type: "function",
|
|
56293
|
+
stateMutability: "nonpayable",
|
|
56294
|
+
inputs: [{ type: "uint256", name: "index" }],
|
|
56295
|
+
outputs: [{ type: "uint256" }]
|
|
56296
|
+
}
|
|
56297
|
+
];
|
|
56298
|
+
|
|
56299
|
+
// src/vaults/lst/withdrawals/readers/binance.ts
|
|
56300
|
+
var readerBinanceWbeth2 = {
|
|
56301
|
+
fetch: async (user, multicallRetry, chainId, entry) => {
|
|
56302
|
+
if (!entry.withdrawalContract) return [];
|
|
56303
|
+
const res = await multicallRetry({
|
|
56304
|
+
chain: chainId,
|
|
56305
|
+
calls: [
|
|
56306
|
+
{
|
|
56307
|
+
address: entry.withdrawalContract,
|
|
56308
|
+
name: "getUserWithdrawRequests",
|
|
56309
|
+
params: [user]
|
|
56310
|
+
},
|
|
56311
|
+
{
|
|
56312
|
+
address: entry.withdrawalContract,
|
|
56313
|
+
name: "lockTime",
|
|
56314
|
+
params: []
|
|
56315
|
+
}
|
|
56316
|
+
],
|
|
56317
|
+
abi: [BinanceUnwrapQueueAbi, BinanceUnwrapQueueAbi]
|
|
56318
|
+
});
|
|
56319
|
+
const reqs = res[0];
|
|
56320
|
+
const lockTime = toNumber(res[1]);
|
|
56321
|
+
if (!Array.isArray(reqs) || lockTime === void 0) return [];
|
|
56322
|
+
const out = [];
|
|
56323
|
+
for (let i = 0; i < reqs.length; i++) {
|
|
56324
|
+
const r = reqs[i];
|
|
56325
|
+
const triggerTime = toNumber(r.triggerTime);
|
|
56326
|
+
const ethAmount = toBigInt14(r.ethAmount);
|
|
56327
|
+
const wbethAmount = toBigInt14(r.wbethAmount);
|
|
56328
|
+
if (triggerTime === void 0 || ethAmount === void 0) continue;
|
|
56329
|
+
const readyAt = triggerTime + lockTime;
|
|
56330
|
+
const claimed = (toNumber(r.claimTime) ?? 0) > 0;
|
|
56331
|
+
const allocated = r.allocated === true;
|
|
56332
|
+
out.push({
|
|
56333
|
+
lst: entry.lst,
|
|
56334
|
+
brand: entry.brand,
|
|
56335
|
+
symbol: entry.symbol,
|
|
56336
|
+
// Positional — see note 1 above.
|
|
56337
|
+
requestId: String(i),
|
|
56338
|
+
amountUnderlying: ethAmount.toString(),
|
|
56339
|
+
shares: wbethAmount?.toString(),
|
|
56340
|
+
// Claimed requests are popped from the array, so this branch is
|
|
56341
|
+
// defensive only.
|
|
56342
|
+
status: claimed ? "claimed" : allocated ? computeStatus(readyAt) : "pending",
|
|
56343
|
+
readyAt
|
|
56344
|
+
});
|
|
56345
|
+
}
|
|
56346
|
+
return out;
|
|
56347
|
+
}
|
|
56348
|
+
};
|
|
56349
|
+
|
|
55830
56350
|
// src/vaults/lst/withdrawals/abis/berapaw.ts
|
|
55831
56351
|
var BeraPawForgeWithdrawalAbi = [
|
|
55832
56352
|
{
|
|
@@ -57968,6 +58488,8 @@ var readerYieldNest = {
|
|
|
57968
58488
|
// src/vaults/lst/withdrawals/readers/index.ts
|
|
57969
58489
|
var buildWithdrawalReader = (entry) => {
|
|
57970
58490
|
switch (entry.reader) {
|
|
58491
|
+
case "binanceWbethQueue":
|
|
58492
|
+
return readerBinanceWbeth2;
|
|
57971
58493
|
case "lidoQueue":
|
|
57972
58494
|
return readerLido;
|
|
57973
58495
|
case "etherfiNft":
|
|
@@ -58033,6 +58555,20 @@ var buildWithdrawalReader = (entry) => {
|
|
|
58033
58555
|
// src/vaults/lst/withdrawals/registry.ts
|
|
58034
58556
|
var LST_WITHDRAWAL_REGISTRY = {
|
|
58035
58557
|
"1": [
|
|
58558
|
+
{
|
|
58559
|
+
// wBETH — Binance's UnwrapTokenV1 queue, the SAME contract address
|
|
58560
|
+
// on Ethereum and BNB. Entered via `wBETH.requestWithdrawEth`;
|
|
58561
|
+
// `getUserWithdrawRequests(user)` enumerates open requests, and
|
|
58562
|
+
// `claimWithdraw(index)` takes the user's ARRAY POSITION (swap-and-pop,
|
|
58563
|
+
// so ids shift on every claim — never cache them). `lockTime()` is
|
|
58564
|
+
// 10 days today but is admin-settable down to 2, and the ETH owed is
|
|
58565
|
+
// frozen at request time, so the position stops earning meanwhile.
|
|
58566
|
+
lst: "0xa2e3356610840701bdf5611a53974510ae27e2e1",
|
|
58567
|
+
brand: "Binance",
|
|
58568
|
+
symbol: "wBETH",
|
|
58569
|
+
reader: "binanceWbethQueue",
|
|
58570
|
+
withdrawalContract: "0x79973d557cd9dd87eb61e250cc2572c990e20196"
|
|
58571
|
+
},
|
|
58036
58572
|
// Ankr ankrETH — Ankr unstake queue; reader not yet implemented.
|
|
58037
58573
|
{
|
|
58038
58574
|
lst: "0xe95a203b1a91a908f9b9ce46459d101078c2c3cb",
|
|
@@ -58405,6 +58941,20 @@ var LST_WITHDRAWAL_REGISTRY = {
|
|
|
58405
58941
|
}
|
|
58406
58942
|
],
|
|
58407
58943
|
"56": [
|
|
58944
|
+
{
|
|
58945
|
+
// wBETH — Binance's UnwrapTokenV1 queue, the SAME contract address
|
|
58946
|
+
// on Ethereum and BNB. Entered via `wBETH.requestWithdrawEth`;
|
|
58947
|
+
// `getUserWithdrawRequests(user)` enumerates open requests, and
|
|
58948
|
+
// `claimWithdraw(index)` takes the user's ARRAY POSITION (swap-and-pop,
|
|
58949
|
+
// so ids shift on every claim — never cache them). `lockTime()` is
|
|
58950
|
+
// 10 days today but is admin-settable down to 2, and the ETH owed is
|
|
58951
|
+
// frozen at request time, so the position stops earning meanwhile.
|
|
58952
|
+
lst: "0xa2e3356610840701bdf5611a53974510ae27e2e1",
|
|
58953
|
+
brand: "Binance",
|
|
58954
|
+
symbol: "wBETH",
|
|
58955
|
+
reader: "binanceWbethQueue",
|
|
58956
|
+
withdrawalContract: "0x79973d557cd9dd87eb61e250cc2572c990e20196"
|
|
58957
|
+
},
|
|
58408
58958
|
// Ankr ankrBNB — Ankr unstake queue; reader not yet implemented.
|
|
58409
58959
|
{
|
|
58410
58960
|
lst: "0x52f24a5e03aee338da5fd9df68d2b6fae1178827",
|
|
@@ -59321,7 +59871,7 @@ query LagoonVaults($where: VaultFilterInput!, $first: Int!, $skip: Int!) {
|
|
|
59321
59871
|
}
|
|
59322
59872
|
}
|
|
59323
59873
|
}`;
|
|
59324
|
-
var
|
|
59874
|
+
var PAGE_SIZE3 = 200;
|
|
59325
59875
|
async function fetchLagoonApiVaults(chainId) {
|
|
59326
59876
|
const out = [];
|
|
59327
59877
|
let skip = 0;
|
|
@@ -59333,7 +59883,7 @@ async function fetchLagoonApiVaults(chainId) {
|
|
|
59333
59883
|
query: VAULTS_QUERY,
|
|
59334
59884
|
variables: {
|
|
59335
59885
|
where: { chainId_eq: Number(chainId), isVisible_eq: true },
|
|
59336
|
-
first:
|
|
59886
|
+
first: PAGE_SIZE3,
|
|
59337
59887
|
skip
|
|
59338
59888
|
}
|
|
59339
59889
|
})
|
|
@@ -59351,8 +59901,8 @@ async function fetchLagoonApiVaults(chainId) {
|
|
|
59351
59901
|
}
|
|
59352
59902
|
const items = json?.data?.vaults?.items ?? [];
|
|
59353
59903
|
out.push(...items);
|
|
59354
|
-
if (items.length <
|
|
59355
|
-
skip +=
|
|
59904
|
+
if (items.length < PAGE_SIZE3) break;
|
|
59905
|
+
skip += PAGE_SIZE3;
|
|
59356
59906
|
}
|
|
59357
59907
|
return out;
|
|
59358
59908
|
}
|
|
@@ -59472,7 +60022,7 @@ var Erc4626TotalAssetsAbi = [
|
|
|
59472
60022
|
|
|
59473
60023
|
// src/vaults/aave-earn/api.ts
|
|
59474
60024
|
var AAVE_EARN_API_URL = "https://api.v3.aave.com/graphql";
|
|
59475
|
-
var
|
|
60025
|
+
var PAGE_SIZE4 = "FIFTY";
|
|
59476
60026
|
var VAULT_FIELDS = `
|
|
59477
60027
|
address
|
|
59478
60028
|
shareName
|
|
@@ -59530,7 +60080,7 @@ async function fetchAaveEarnApiVaults(chainId, targets) {
|
|
|
59530
60080
|
for (let page = 0; page < 20; page++) {
|
|
59531
60081
|
const request = {
|
|
59532
60082
|
criteria: { ownedBy: [owner] },
|
|
59533
|
-
pageSize:
|
|
60083
|
+
pageSize: PAGE_SIZE4
|
|
59534
60084
|
};
|
|
59535
60085
|
if (cursor) request.cursor = cursor;
|
|
59536
60086
|
const data = await postGraphql(OWNED_VAULTS_QUERY, { request });
|
|
@@ -59789,47 +60339,6 @@ var fetchUpshiftVaults = async (chainId, prices = {}, tokenList = {}) => {
|
|
|
59789
60339
|
return out;
|
|
59790
60340
|
};
|
|
59791
60341
|
|
|
59792
|
-
// src/vaults/yearn/api.ts
|
|
59793
|
-
var YEARN_YDAEMON_BASE = "https://ydaemon.yearn.fi";
|
|
59794
|
-
var YEARN_CHAIN_IDS = /* @__PURE__ */ new Set([
|
|
59795
|
-
"1",
|
|
59796
|
-
// Ethereum
|
|
59797
|
-
"137",
|
|
59798
|
-
// Polygon
|
|
59799
|
-
"8453",
|
|
59800
|
-
// Base
|
|
59801
|
-
"42161",
|
|
59802
|
-
// Arbitrum
|
|
59803
|
-
"100",
|
|
59804
|
-
// Gnosis
|
|
59805
|
-
"146",
|
|
59806
|
-
// Sonic
|
|
59807
|
-
"747474"
|
|
59808
|
-
// Katana
|
|
59809
|
-
]);
|
|
59810
|
-
var hasYearnVaults = (chainId) => YEARN_CHAIN_IDS.has(String(chainId));
|
|
59811
|
-
var isYearnV3 = (v) => typeof v?.version === "string" && v.version.startsWith("3.");
|
|
59812
|
-
var PAGE_SIZE4 = 500;
|
|
59813
|
-
async function fetchYearnApiVaults(chainId) {
|
|
59814
|
-
const out = [];
|
|
59815
|
-
for (let page = 1; page <= 20; page++) {
|
|
59816
|
-
const url = `${YEARN_YDAEMON_BASE}/${chainId}/vaults/all?limit=${PAGE_SIZE4}&page=${page}`;
|
|
59817
|
-
const response = await fetch(url);
|
|
59818
|
-
if (!response.ok) {
|
|
59819
|
-
throw new Error(
|
|
59820
|
-
`Yearn yDaemon API failed: ${response.status} - ${response.statusText}`
|
|
59821
|
-
);
|
|
59822
|
-
}
|
|
59823
|
-
const items = await response.json();
|
|
59824
|
-
if (!Array.isArray(items)) break;
|
|
59825
|
-
for (const v of items) {
|
|
59826
|
-
if (isYearnV3(v) && v.endorsed) out.push(v);
|
|
59827
|
-
}
|
|
59828
|
-
if (items.length < PAGE_SIZE4) break;
|
|
59829
|
-
}
|
|
59830
|
-
return out;
|
|
59831
|
-
}
|
|
59832
|
-
|
|
59833
60342
|
// src/vaults/yearn/fetchPublic.ts
|
|
59834
60343
|
var BRAND3 = "Yearn";
|
|
59835
60344
|
var ZERO_ADDR = "0x0000000000000000000000000000000000000000";
|
|
@@ -59875,7 +60384,7 @@ var asBig = (v) => {
|
|
|
59875
60384
|
}
|
|
59876
60385
|
};
|
|
59877
60386
|
var num9 = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
59878
|
-
var
|
|
60387
|
+
var toPct2 = (v) => {
|
|
59879
60388
|
const n = num9(v);
|
|
59880
60389
|
return n == null ? 0 : n * 100;
|
|
59881
60390
|
};
|
|
@@ -59911,9 +60420,9 @@ function parseVault9(v, chainId, prices, tokenList) {
|
|
|
59911
60420
|
const realized = num9(v.apr?.netAPR);
|
|
59912
60421
|
const forward = num9(v.apr?.forwardAPR?.netAPR);
|
|
59913
60422
|
const isForwardApr = realized == null && forward != null;
|
|
59914
|
-
const supplyRate =
|
|
59915
|
-
const rewardsRate =
|
|
59916
|
-
const fee =
|
|
60423
|
+
const supplyRate = toPct2(realized ?? forward);
|
|
60424
|
+
const rewardsRate = toPct2(v.apr?.extra?.stakingRewardsAPR);
|
|
60425
|
+
const fee = toPct2(v.apr?.fees?.performance);
|
|
59917
60426
|
const oracleKey = toOracleKey(assetMeta?.assetGroup) ?? toGenericPriceKey(assetAddr, chainId);
|
|
59918
60427
|
const apiPrice = num9(v.tvl?.price) ?? 0;
|
|
59919
60428
|
const priceUsd = prices[oracleKey] ?? prices[assetAddr] ?? apiPrice;
|
|
@@ -64697,11 +65206,12 @@ var llamaLendAdapter = {
|
|
|
64697
65206
|
/**
|
|
64698
65207
|
* The band count as an editable TERM, not just a curve to read.
|
|
64699
65208
|
*
|
|
64700
|
-
* `bandLtv` alone cannot drive a control: it is
|
|
64701
|
-
*
|
|
64702
|
-
*
|
|
64703
|
-
*
|
|
64704
|
-
*
|
|
65209
|
+
* `bandLtv` alone cannot drive a control: it is missing on any
|
|
65210
|
+
* market whose geometry could not be read. The domain is always
|
|
65211
|
+
* known — `MIN_TICKS`/`MAX_TICKS` are 4..50 on both generations — so
|
|
65212
|
+
* the control works even where the curve does not. Where the curve
|
|
65213
|
+
* IS present it spans the full domain, so a control can show the LTV
|
|
65214
|
+
* for every value it offers.
|
|
64705
65215
|
*
|
|
64706
65216
|
* `immutableAfterOpen` is what tells the UI to render this read-only
|
|
64707
65217
|
* on an existing loan: `_add_collateral_borrow` reuses the tick
|
|
@@ -64766,7 +65276,16 @@ var frankencoinAdapter = {
|
|
|
64766
65276
|
return {
|
|
64767
65277
|
// Not a coverage hole: the protocol has no price feed by design.
|
|
64768
65278
|
oracle: { kind: "none" },
|
|
65279
|
+
supply: {
|
|
65280
|
+
// Collateral inside a position. There is no ZCHF lending deposit at
|
|
65281
|
+
// all — the earn surface is the savings module, a separate provider —
|
|
65282
|
+
// so this side never pays interest.
|
|
65283
|
+
role: "collateral",
|
|
65284
|
+
availability: { opensWith: "both-legs" },
|
|
65285
|
+
counterparty: { kind: "cdp", solvency: "overcollateralized" }
|
|
65286
|
+
},
|
|
64769
65287
|
borrow: {
|
|
65288
|
+
availability: { opensWith: "both-legs" },
|
|
64770
65289
|
debtShape: "accruing",
|
|
64771
65290
|
maturity: expiration > 0 ? {
|
|
64772
65291
|
kind: "fixed-date",
|