@1delta/margin-fetcher 5.0.16 → 5.0.18
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/README.md +164 -116
- package/dist/index.d.ts +22 -0
- package/dist/index.js +556 -79
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -7056,9 +7056,9 @@ var calculateRateForCompoundType2 = (n) => {
|
|
|
7056
7056
|
const rate = Number(formatEther(BigInt(n)));
|
|
7057
7057
|
return (Math.pow(rate * 60 * 60 * 24 / 12 + 1, 365) - 1) * 100;
|
|
7058
7058
|
};
|
|
7059
|
-
var calculateRateForCompoundType = (n, chainId,
|
|
7059
|
+
var calculateRateForCompoundType = (n, chainId, scale3 = 1 /* SECOND */) => {
|
|
7060
7060
|
const rate = Number(formatEther(BigInt(n)));
|
|
7061
|
-
if (
|
|
7061
|
+
if (scale3 === 0 /* BLOCK */)
|
|
7062
7062
|
return (Math.pow(
|
|
7063
7063
|
rate * 60 * 60 * 24 / (BLOCK_TIMES[chainId] ?? "1") + 1,
|
|
7064
7064
|
365
|
|
@@ -17642,7 +17642,16 @@ function buildEModes(borrowVaults, cluster) {
|
|
|
17642
17642
|
}
|
|
17643
17643
|
return eModes;
|
|
17644
17644
|
}
|
|
17645
|
+
var OP_DEPOSIT = 1 << 0;
|
|
17646
|
+
var OP_MINT = 1 << 1;
|
|
17647
|
+
var OP_BORROW = 1 << 6;
|
|
17648
|
+
function isOperationDisabled(info, operation) {
|
|
17649
|
+
const hookedOps = Number(info.hookedOperations ?? 0n);
|
|
17650
|
+
return (hookedOps & operation) !== 0 && info.hookTarget.toLowerCase() === zeroAddress;
|
|
17651
|
+
}
|
|
17645
17652
|
function buildMetadata(info) {
|
|
17653
|
+
const hookedOperations = Number(info.hookedOperations ?? 0n);
|
|
17654
|
+
const hookTarget = info.hookTarget.toLowerCase();
|
|
17646
17655
|
return {
|
|
17647
17656
|
vault: info.vault.toLowerCase(),
|
|
17648
17657
|
dToken: info.dToken.toLowerCase(),
|
|
@@ -17650,7 +17659,9 @@ function buildMetadata(info) {
|
|
|
17650
17659
|
interestRateModel: info.interestRateModel.toLowerCase(),
|
|
17651
17660
|
unitOfAccount: info.unitOfAccount.toLowerCase(),
|
|
17652
17661
|
evc: info.evc.toLowerCase(),
|
|
17653
|
-
governorAdmin: info.governorAdmin.toLowerCase()
|
|
17662
|
+
governorAdmin: info.governorAdmin.toLowerCase(),
|
|
17663
|
+
...hookedOperations !== 0 ? { hookedOperations } : {},
|
|
17664
|
+
...hookTarget !== zeroAddress ? { hookTarget } : {}
|
|
17654
17665
|
};
|
|
17655
17666
|
}
|
|
17656
17667
|
function buildTokenEntry(info, config, collateralActive, borrowVaults, opts) {
|
|
@@ -17707,13 +17718,32 @@ function buildTokenEntry(info, config, collateralActive, borrowVaults, opts) {
|
|
|
17707
17718
|
lastUpdateTimestamp: Number(info.timestamp),
|
|
17708
17719
|
config,
|
|
17709
17720
|
collateralActive,
|
|
17710
|
-
|
|
17711
|
-
|
|
17721
|
+
// A governor can switch either side of a vault off through the hook system
|
|
17722
|
+
// without ever touching the caps, so these flags are read from
|
|
17723
|
+
// `hookedOperations`/`hookTarget` rather than assumed. A vault that takes no
|
|
17724
|
+
// deposits is not a collateral candidate and must not rank as one, however
|
|
17725
|
+
// attractive its rate — `maxDeposit`/`maxMint` return 0 for it on-chain.
|
|
17726
|
+
borrowingEnabled: isBorrowVault && !isOperationDisabled(info, OP_BORROW),
|
|
17727
|
+
// Gated on OP_DEPOSIT alone, not on `OP_DEPOSIT || OP_MINT`: every supply
|
|
17728
|
+
// route we encode calls `deposit`, so a vault that disabled only that leg is
|
|
17729
|
+
// unusable to us even while share-minting stays open.
|
|
17730
|
+
depositsEnabled: !isOperationDisabled(info, OP_DEPOSIT),
|
|
17712
17731
|
hasStable: false,
|
|
17713
17732
|
isActive: true,
|
|
17714
|
-
|
|
17733
|
+
// Supply AND borrow both off is the closest EVK analogue of an Aave-style
|
|
17734
|
+
// freeze: the vault still prices and still lets existing positions unwind.
|
|
17735
|
+
isFrozen: isOperationDisabled(info, OP_DEPOSIT) && isOperationDisabled(info, OP_MINT) && isOperationDisabled(info, OP_BORROW),
|
|
17715
17736
|
borrowCap: toTokenAmount(info.borrowCap, info.assetDecimals),
|
|
17716
|
-
|
|
17737
|
+
// Supply switched off reports as ZERO CAPACITY, not merely as a false flag.
|
|
17738
|
+
// Consumers that rank markets (the pair book) can only compare capacity
|
|
17739
|
+
// across lenders — `depositsEnabled` means different things per provider
|
|
17740
|
+
// (Gearbox marks collateral-only tokens false because they have no lend
|
|
17741
|
+
// side, while they remain perfectly good collateral), so it cannot be a
|
|
17742
|
+
// cross-lender gate. Capacity can, and 0 is exactly what the vault's own
|
|
17743
|
+
// `maxDeposit`/`maxMint` return here. Note this is already the shape Euler
|
|
17744
|
+
// itself emits for a cap-disabled vault: `caps() = (1, …)` resolves to a
|
|
17745
|
+
// supply cap of 0.
|
|
17746
|
+
supplyCap: isOperationDisabled(info, OP_DEPOSIT) ? 0 : toTokenAmount(info.supplyCap, info.assetDecimals),
|
|
17717
17747
|
debtCeiling: 0,
|
|
17718
17748
|
eMode: selfEMode,
|
|
17719
17749
|
decimals: Number(info.assetDecimals),
|
|
@@ -20594,8 +20624,8 @@ var TermSubgraphSource = class {
|
|
|
20594
20624
|
const auction = data.termAuctions?.[0];
|
|
20595
20625
|
const clearingRate = toNum(auction?.auctionClearingPrice);
|
|
20596
20626
|
const aprPct = clearingRate > 0 ? clearingRate / WAD3 * 100 : 0;
|
|
20597
|
-
const
|
|
20598
|
-
const toLoan = (repoUnits) => Number(repoUnits * redemptionRatio / BigInt(WAD3)) /
|
|
20627
|
+
const scale3 = Math.pow(10, config.loanDecimals);
|
|
20628
|
+
const toLoan = (repoUnits) => Number(repoUnits * redemptionRatio / BigInt(WAD3)) / scale3;
|
|
20599
20629
|
const orders = (data.termOrders ?? []).map((o) => ({
|
|
20600
20630
|
remaining: toBig3(o.originalOrderAmount) - toBig3(o.filledAmount),
|
|
20601
20631
|
isAsk: String(o.makerToken).toLowerCase() === repoToken
|
|
@@ -20684,7 +20714,7 @@ var TermSubgraphSource = class {
|
|
|
20684
20714
|
{ term, who }
|
|
20685
20715
|
);
|
|
20686
20716
|
if (!data) return null;
|
|
20687
|
-
const
|
|
20717
|
+
const scale3 = Math.pow(10, config.loanDecimals);
|
|
20688
20718
|
const toOrder = (o, side, revealedRaw) => {
|
|
20689
20719
|
const a = o.auction ?? {};
|
|
20690
20720
|
const complete = Boolean(a.auctionComplete);
|
|
@@ -20696,7 +20726,7 @@ var TermSubgraphSource = class {
|
|
|
20696
20726
|
auctionId: String(a.id ?? ""),
|
|
20697
20727
|
account,
|
|
20698
20728
|
amount: String(o.amount ?? "0"),
|
|
20699
|
-
assets: Number(toBig3(o.amount)) /
|
|
20729
|
+
assets: Number(toBig3(o.amount)) / scale3,
|
|
20700
20730
|
assignedAmount: String(o.assignedAmount ?? "0"),
|
|
20701
20731
|
locked: Boolean(o.locked),
|
|
20702
20732
|
revealed,
|
|
@@ -22978,7 +23008,6 @@ function num(api, key2) {
|
|
|
22978
23008
|
const v = api?.[key2];
|
|
22979
23009
|
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
22980
23010
|
}
|
|
22981
|
-
var BANDS_ENDPOINTS = [4, 10, 20, 50];
|
|
22982
23011
|
var DEFAULT_BANDS = 10;
|
|
22983
23012
|
var LLAMALEND_READ_ABI = [
|
|
22984
23013
|
...LlamaLendControllerAbi,
|
|
@@ -22989,6 +23018,8 @@ var LLAMALEND_READ_ABI = [
|
|
|
22989
23018
|
...Erc20Abi
|
|
22990
23019
|
];
|
|
22991
23020
|
var ZERO = "0x0000000000000000000000000000000000000000";
|
|
23021
|
+
var WAD8 = 10n ** 18n;
|
|
23022
|
+
var CALLS_PER_MARKET = 6;
|
|
22992
23023
|
var fetchJson2 = async (url, timeoutMs = 8e3) => {
|
|
22993
23024
|
const res = await fetch(url, {
|
|
22994
23025
|
headers: { accept: "application/json" },
|
|
@@ -23005,25 +23036,12 @@ var toBig5 = (v) => {
|
|
|
23005
23036
|
};
|
|
23006
23037
|
var human = (v, decimals) => v === null ? null : Number(v) / 10 ** decimals;
|
|
23007
23038
|
var bandsFor = (m) => m.defaultBands && m.defaultBands >= 4 && m.defaultBands <= 50 ? m.defaultBands : DEFAULT_BANDS;
|
|
23008
|
-
var bandGrid = (m) => {
|
|
23009
|
-
const set = /* @__PURE__ */ new Set([...BANDS_ENDPOINTS, bandsFor(m)]);
|
|
23010
|
-
return [...set].sort((a, b) => a - b);
|
|
23011
|
-
};
|
|
23012
23039
|
var MIN_BANDS = 4;
|
|
23013
23040
|
var MAX_BANDS = 50;
|
|
23014
23041
|
var LTV_CURVE_BANDS = Array.from(
|
|
23015
23042
|
{ length: MAX_BANDS - MIN_BANDS + 1 },
|
|
23016
23043
|
(_3, i) => MIN_BANDS + i
|
|
23017
23044
|
);
|
|
23018
|
-
var maxBorrowableCall = (m, oneUnit, n) => m.version === 1 ? {
|
|
23019
|
-
address: m.controller,
|
|
23020
|
-
name: "max_borrowable",
|
|
23021
|
-
params: [oneUnit, BigInt(n), 0n, ZERO]
|
|
23022
|
-
} : {
|
|
23023
|
-
address: m.controller,
|
|
23024
|
-
name: "max_borrowable",
|
|
23025
|
-
params: [oneUnit, BigInt(n), ZERO]
|
|
23026
|
-
};
|
|
23027
23045
|
var buildBandLtv = (market) => {
|
|
23028
23046
|
if (!market.ammA || !market.loanDiscount) return null;
|
|
23029
23047
|
try {
|
|
@@ -23044,8 +23062,6 @@ var buildBandLtv = (market) => {
|
|
|
23044
23062
|
};
|
|
23045
23063
|
async function fetchChainExtras(chainId, markets) {
|
|
23046
23064
|
const perMarketCalls = markets.map((m) => {
|
|
23047
|
-
const grid = bandGrid(m);
|
|
23048
|
-
const oneUnit = 10n ** BigInt(m.collateralDecimals);
|
|
23049
23065
|
const calls = [
|
|
23050
23066
|
{ address: m.amm, name: "price_oracle", params: [] },
|
|
23051
23067
|
{ address: m.amm, name: "active_band", params: [] },
|
|
@@ -23054,9 +23070,17 @@ async function fetchChainExtras(chainId, markets) {
|
|
|
23054
23070
|
// v1 controllers have no `borrow_cap`; allowFailure turns that into a
|
|
23055
23071
|
// null rather than sinking the whole batch.
|
|
23056
23072
|
{ address: m.controller, name: "borrow_cap", params: [] },
|
|
23057
|
-
|
|
23073
|
+
/**
|
|
23074
|
+
* Price per share, read ONCE PER MARKET rather than per user.
|
|
23075
|
+
*
|
|
23076
|
+
* Vault shares run ~1000x the asset scale (`DEAD_SHARES`), so a share
|
|
23077
|
+
* balance is never an amount — every consumer needs this multiplier to
|
|
23078
|
+
* turn a lender's holding into assets. Reading it here keeps the
|
|
23079
|
+
* per-user call to two plain `balanceOf`s.
|
|
23080
|
+
*/
|
|
23081
|
+
{ address: m.vault, name: "convertToAssets", params: [WAD8] }
|
|
23058
23082
|
];
|
|
23059
|
-
return { market: m,
|
|
23083
|
+
return { market: m, calls };
|
|
23060
23084
|
});
|
|
23061
23085
|
const flat = perMarketCalls.flatMap((x) => x.calls);
|
|
23062
23086
|
if (flat.length === 0) return {};
|
|
@@ -23077,13 +23101,14 @@ async function fetchChainExtras(chainId, markets) {
|
|
|
23077
23101
|
}
|
|
23078
23102
|
const out = {};
|
|
23079
23103
|
let cursor = 0;
|
|
23080
|
-
for (const { market
|
|
23104
|
+
for (const { market } of perMarketCalls) {
|
|
23081
23105
|
const priceRaw = toBig5(results[cursor]);
|
|
23082
23106
|
const activeBandRaw = toBig5(results[cursor + 1]);
|
|
23083
23107
|
const nLoansRaw = toBig5(results[cursor + 2]);
|
|
23084
23108
|
const maxDepositRaw = toBig5(results[cursor + 3]);
|
|
23085
23109
|
const borrowCapRaw = toBig5(results[cursor + 4]);
|
|
23086
|
-
|
|
23110
|
+
const pricePerShareRaw = toBig5(results[cursor + 5]);
|
|
23111
|
+
cursor += CALLS_PER_MARKET;
|
|
23087
23112
|
const collateralPrice = priceRaw === null ? null : Number(priceRaw) / 1e18;
|
|
23088
23113
|
const bandLtv = buildBandLtv(market);
|
|
23089
23114
|
const defaultN = String(bandsFor(market));
|
|
@@ -23094,7 +23119,11 @@ async function fetchChainExtras(chainId, markets) {
|
|
|
23094
23119
|
borrowCap: human(borrowCapRaw, market.borrowedDecimals),
|
|
23095
23120
|
maxDeposit: human(maxDepositRaw, market.borrowedDecimals),
|
|
23096
23121
|
nLoans: nLoansRaw === null ? null : Number(nLoansRaw),
|
|
23097
|
-
activeBand: activeBandRaw === null ? null : Number(activeBandRaw)
|
|
23122
|
+
activeBand: activeBandRaw === null ? null : Number(activeBandRaw),
|
|
23123
|
+
// Assets-per-WAD-shares. Kept as a ratio (not scaled to the borrowed
|
|
23124
|
+
// token's decimals) so a consumer multiplies a raw share balance by it
|
|
23125
|
+
// and divides by 1e18 exactly once.
|
|
23126
|
+
pricePerShare: pricePerShareRaw === null ? null : Number(pricePerShareRaw) / 1e18
|
|
23098
23127
|
};
|
|
23099
23128
|
}
|
|
23100
23129
|
return out;
|
|
@@ -23159,7 +23188,8 @@ async function fetchLlamaLendMarkets(lender, chainId) {
|
|
|
23159
23188
|
),
|
|
23160
23189
|
maxDeposit: ex?.maxDeposit ?? null,
|
|
23161
23190
|
nLoans: ex?.nLoans ?? null,
|
|
23162
|
-
activeBand: ex?.activeBand ?? null
|
|
23191
|
+
activeBand: ex?.activeBand ?? null,
|
|
23192
|
+
pricePerShare: ex?.pricePerShare ?? null
|
|
23163
23193
|
};
|
|
23164
23194
|
});
|
|
23165
23195
|
return { lender, config, chainData, markets: rows, source: "api" };
|
|
@@ -23219,7 +23249,8 @@ async function fetchLlamaLendMarkets(lender, chainId) {
|
|
|
23219
23249
|
),
|
|
23220
23250
|
maxDeposit: ex?.maxDeposit ?? null,
|
|
23221
23251
|
nLoans: ex?.nLoans ?? null,
|
|
23222
|
-
activeBand: ex?.activeBand ?? null
|
|
23252
|
+
activeBand: ex?.activeBand ?? null,
|
|
23253
|
+
pricePerShare: ex?.pricePerShare ?? null
|
|
23223
23254
|
};
|
|
23224
23255
|
});
|
|
23225
23256
|
return { lender, config, chainData, markets: rows, source: "chain" };
|
|
@@ -24411,6 +24442,13 @@ function convertLlamaLendMarketsToResponse(raw, chainId, prices = {}, additional
|
|
|
24411
24442
|
collateralPrice: m.collateralPrice !== null ? String(m.collateralPrice) : void 0,
|
|
24412
24443
|
/** v2 only; `0` means borrowing is switched off. */
|
|
24413
24444
|
borrowCap: m.borrowCap !== null ? String(m.borrowCap) : void 0,
|
|
24445
|
+
/**
|
|
24446
|
+
* Assets per 1e18 vault shares — what a lender's share balance is
|
|
24447
|
+
* worth. Published because the SUPPLY side of a LlamaLend market is
|
|
24448
|
+
* an ERC-4626 vault whose shares run ~1000x the asset scale, so a
|
|
24449
|
+
* raw balance is meaningless without it.
|
|
24450
|
+
*/
|
|
24451
|
+
pricePerShare: m.pricePerShare !== null ? String(m.pricePerShare) : void 0,
|
|
24414
24452
|
addresses: {
|
|
24415
24453
|
controller: market.controller,
|
|
24416
24454
|
vault: market.vault,
|
|
@@ -24514,7 +24552,7 @@ function ratePerSecToApr(rate) {
|
|
|
24514
24552
|
return Number(rate) / 1e18 * SECONDS_PER_YEAR9 * 100;
|
|
24515
24553
|
}
|
|
24516
24554
|
function buildRewardEntries(p, rsup, chainId, prices, tokens, collateralUsd, debtUsd) {
|
|
24517
|
-
const
|
|
24555
|
+
const priceOf2 = (address) => {
|
|
24518
24556
|
const lower3 = address.toLowerCase();
|
|
24519
24557
|
const token = tokens[lower3];
|
|
24520
24558
|
const key2 = toOracleKey(token?.assetGroup) || toGenericPriceKey(lower3, chainId);
|
|
@@ -24523,7 +24561,7 @@ function buildRewardEntries(p, rsup, chainId, prices, tokens, collateralUsd, deb
|
|
|
24523
24561
|
const collateral = [];
|
|
24524
24562
|
if (collateralUsd > 0) {
|
|
24525
24563
|
for (const r of p.collateralRewards ?? []) {
|
|
24526
|
-
const price2 =
|
|
24564
|
+
const price2 = priceOf2(r.token);
|
|
24527
24565
|
if (price2 <= 0) continue;
|
|
24528
24566
|
const decimals = tokens[r.token.toLowerCase()]?.decimals ?? 18;
|
|
24529
24567
|
const perSecond = Number(r.ratePerSecPerShare) * Number(p.totalCollateral ?? 0n) / 1e18;
|
|
@@ -24540,7 +24578,7 @@ function buildRewardEntries(p, rsup, chainId, prices, tokens, collateralUsd, deb
|
|
|
24540
24578
|
}
|
|
24541
24579
|
const borrow = [];
|
|
24542
24580
|
if (rsup && debtUsd > 0 && (p.rsupWeight ?? 0n) > 0n) {
|
|
24543
|
-
const price2 =
|
|
24581
|
+
const price2 = priceOf2(rsup.govToken);
|
|
24544
24582
|
if (price2 > 0) {
|
|
24545
24583
|
const decimals = tokens[rsup.govToken.toLowerCase()]?.decimals ?? 18;
|
|
24546
24584
|
const perSecond = Number(rsup.rewardRate) * Number(p.rsupWeight) / Number(rsup.totalWeight);
|
|
@@ -25109,7 +25147,7 @@ function dssKeyParts(key2) {
|
|
|
25109
25147
|
if (!m) return void 0;
|
|
25110
25148
|
return { lender: m[1], chainId: m[2], ilk: keySegmentToIlk(m[3]) };
|
|
25111
25149
|
}
|
|
25112
|
-
var
|
|
25150
|
+
var WAD10 = 1e18;
|
|
25113
25151
|
var RAY4 = 1e27;
|
|
25114
25152
|
var RAD = 1e45;
|
|
25115
25153
|
var YEAR_SECONDS2 = 31536e3;
|
|
@@ -25153,7 +25191,7 @@ function convertDssMarketsToResponse(raw, chainId, prices = {}, _additionalYield
|
|
|
25153
25191
|
const totalColl = m.joinBalance !== null ? toHuman4(m.joinBalance, collDecimals) : 0;
|
|
25154
25192
|
const mat = m.mat !== null ? Number(m.mat) / RAY4 : Number(market.mat) / RAY4 || 1.5;
|
|
25155
25193
|
const ltv = mat > 0 ? 1 / mat : 0;
|
|
25156
|
-
const chop = market.chop ? Number(market.chop) /
|
|
25194
|
+
const chop = market.chop ? Number(market.chop) / WAD10 : 0;
|
|
25157
25195
|
const liqPenalty = chop > 1 ? chop - 1 : 0;
|
|
25158
25196
|
const duty = m.duty !== null ? m.duty : BigInt(market.duty ?? 0);
|
|
25159
25197
|
const borrowApr = duty > BigInt(1e27) ? Number(duty - BigInt(10) ** BigInt(27)) / RAY4 * YEAR_SECONDS2 * 100 : 0;
|
|
@@ -27885,7 +27923,7 @@ var buildRiverUserCall = (chainId, lender, account) => {
|
|
|
27885
27923
|
});
|
|
27886
27924
|
return calls;
|
|
27887
27925
|
};
|
|
27888
|
-
var LLAMALEND_CALLS_PER_MARKET =
|
|
27926
|
+
var LLAMALEND_CALLS_PER_MARKET = 8;
|
|
27889
27927
|
var buildLlamaLendUserCall = (chainId, lender, account, spender) => {
|
|
27890
27928
|
const cfg = llamaLendConfigFor(lender, chainId);
|
|
27891
27929
|
const markets = llamaLendChainData(lender, chainId)?.markets ?? [];
|
|
@@ -27896,7 +27934,16 @@ var buildLlamaLendUserCall = (chainId, lender, account, spender) => {
|
|
|
27896
27934
|
{ address: m.controller, name: "health", params: [account, true] },
|
|
27897
27935
|
{ address: m.controller, name: "user_prices", params: [account] },
|
|
27898
27936
|
{ address: m.amm, name: "read_user_tick_numbers", params: [account] },
|
|
27899
|
-
{ address: m.controller, name: "approval", params: [account, delegate] }
|
|
27937
|
+
{ address: m.controller, name: "approval", params: [account, delegate] },
|
|
27938
|
+
{ address: m.vault, name: "balanceOf", params: [account] },
|
|
27939
|
+
// A market without a gauge would call address(0), which returns '0x' and
|
|
27940
|
+
// parses as zero — the layout stays fixed either way.
|
|
27941
|
+
{
|
|
27942
|
+
address: m.gauge ?? "0x0000000000000000000000000000000000000000",
|
|
27943
|
+
name: "balanceOf",
|
|
27944
|
+
params: [account]
|
|
27945
|
+
},
|
|
27946
|
+
{ address: m.vault, name: "convertToAssets", params: [10n ** 18n] }
|
|
27900
27947
|
]);
|
|
27901
27948
|
};
|
|
27902
27949
|
var INVERSE_CALLS_PER_MARKET = 4;
|
|
@@ -31073,7 +31120,7 @@ var getMidnightUserDataConverter = (_lender, chainId, account, meta) => {
|
|
|
31073
31120
|
totalCalls
|
|
31074
31121
|
];
|
|
31075
31122
|
};
|
|
31076
|
-
var
|
|
31123
|
+
var WAD11 = 1000000000000000000n;
|
|
31077
31124
|
function toBigInt11(v) {
|
|
31078
31125
|
if (v === void 0 || v === null || v === "0x") return 0n;
|
|
31079
31126
|
if (typeof v === "bigint") return v;
|
|
@@ -31115,8 +31162,8 @@ var getTermUserDataConverter = (_lender, chainId, account, meta) => {
|
|
|
31115
31162
|
const debtStr = parseRawAmount(debtUnits.toString(), market.loanDecimals);
|
|
31116
31163
|
const debtNum = Number(debtStr);
|
|
31117
31164
|
const repoBalance = toBigInt11(balanceResult);
|
|
31118
|
-
const redemptionValue = toBigInt11(redemptionResult) || toBigInt11(market.redemptionValue) ||
|
|
31119
|
-
const lentUnits = repoBalance * redemptionValue /
|
|
31165
|
+
const redemptionValue = toBigInt11(redemptionResult) || toBigInt11(market.redemptionValue) || WAD11;
|
|
31166
|
+
const lentUnits = repoBalance * redemptionValue / WAD11;
|
|
31120
31167
|
const depositsStr = parseRawAmount(lentUnits.toString(), market.loanDecimals);
|
|
31121
31168
|
const depositsNum = Number(depositsStr);
|
|
31122
31169
|
const posData = {};
|
|
@@ -31194,7 +31241,7 @@ var getTermUserDataConverter = (_lender, chainId, account, meta) => {
|
|
|
31194
31241
|
};
|
|
31195
31242
|
var nowSec6 = () => Math.floor(Date.now() / 1e3);
|
|
31196
31243
|
var DAY_SECONDS = 86400n;
|
|
31197
|
-
var
|
|
31244
|
+
var WAD12 = 10n ** 18n;
|
|
31198
31245
|
function sumPreview(positions) {
|
|
31199
31246
|
return positions.reduce((acc, p) => acc + p.previewValue, 0n);
|
|
31200
31247
|
}
|
|
@@ -31218,7 +31265,7 @@ function toDetail(positions, kind, now, penaltyRate, penaltyApr) {
|
|
|
31218
31265
|
...kind === "borrow" ? {
|
|
31219
31266
|
...overdue ? { latePenalty: excess.toString() } : { earlyRepayDiscount: gap.toString() },
|
|
31220
31267
|
// face × penaltyRate × 1 day — what another day of being late adds.
|
|
31221
|
-
latePenaltyPerDay: (face * penaltyRate * DAY_SECONDS /
|
|
31268
|
+
latePenaltyPerDay: (face * penaltyRate * DAY_SECONDS / WAD12).toString(),
|
|
31222
31269
|
latePenaltyApr: penaltyApr
|
|
31223
31270
|
} : {
|
|
31224
31271
|
...overdue ? {} : { earlyExitCost: gap.toString() },
|
|
@@ -31347,7 +31394,7 @@ var getExactlyUserDataConverter = (_lender, chainId, account, meta) => {
|
|
|
31347
31394
|
latePenalty: penalty,
|
|
31348
31395
|
/** further penalty per day overdue — linear on face */
|
|
31349
31396
|
latePenaltyPerDay: parseRawAmount(
|
|
31350
|
-
(face * m.penaltyRate * DAY_SECONDS /
|
|
31397
|
+
(face * m.penaltyRate * DAY_SECONDS / WAD12).toString(),
|
|
31351
31398
|
decimals
|
|
31352
31399
|
),
|
|
31353
31400
|
latePenaltyApr: penaltyApr,
|
|
@@ -31875,7 +31922,13 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
31875
31922
|
const bandBorrowed = big7(stateRaw[1]);
|
|
31876
31923
|
const debt = big7(stateRaw[2]);
|
|
31877
31924
|
const bandCount = Number(big7(stateRaw[3]));
|
|
31878
|
-
|
|
31925
|
+
const vaultSharesRaw = data[base + 5];
|
|
31926
|
+
const gaugeSharesRaw = data[base + 6];
|
|
31927
|
+
const vaultShares = isFailedCall(vaultSharesRaw) ? 0n : big7(vaultSharesRaw);
|
|
31928
|
+
const gaugeShares = isFailedCall(gaugeSharesRaw) ? 0n : big7(gaugeSharesRaw);
|
|
31929
|
+
const lendShares = vaultShares + gaugeShares;
|
|
31930
|
+
if (collateral === 0n && debt === 0n && bandBorrowed === 0n && lendShares === 0n)
|
|
31931
|
+
return;
|
|
31879
31932
|
const healthRaw = data[base + 1];
|
|
31880
31933
|
const health = isFailedCall(healthRaw) ? 0n : big7(healthRaw);
|
|
31881
31934
|
const pricesRaw = data[base + 2];
|
|
@@ -31902,6 +31955,15 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
31902
31955
|
const loanDisplay = loanMeta ? getDisplayPrice(loanMeta) : 0;
|
|
31903
31956
|
const loanOracle = loanMeta ? getOraclePrice(loanMeta) : 0;
|
|
31904
31957
|
const loanHist = loanMeta?.price?.priceUsd24h ?? loanDisplay;
|
|
31958
|
+
const shareToAssetRaw = data[base + 7];
|
|
31959
|
+
const shareToAsset = isFailedCall(shareToAssetRaw) ? 0n : big7(shareToAssetRaw);
|
|
31960
|
+
const lendAssets = shareToAsset === 0n ? 0n : lendShares * shareToAsset / 10n ** 18n;
|
|
31961
|
+
const lendStr = parseRawAmount(lendAssets.toString(), loanDecimals);
|
|
31962
|
+
const depositStr = parseRawAmount(
|
|
31963
|
+
(lendAssets + bandBorrowed).toString(),
|
|
31964
|
+
loanDecimals
|
|
31965
|
+
);
|
|
31966
|
+
const depositNum = Number(depositStr);
|
|
31905
31967
|
const llamalendInfo = {
|
|
31906
31968
|
health: health.toString(),
|
|
31907
31969
|
priceUpper: priceUpper.toString(),
|
|
@@ -31909,6 +31971,9 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
31909
31971
|
bands,
|
|
31910
31972
|
bandCount,
|
|
31911
31973
|
bandCollateralInBorrowed: bandBorrowed.toString(),
|
|
31974
|
+
lendAssets: lendStr,
|
|
31975
|
+
lendShares: lendShares.toString(),
|
|
31976
|
+
lendStaked: gaugeShares > 0n,
|
|
31912
31977
|
softLiquidating: bandBorrowed > 0n,
|
|
31913
31978
|
delegated,
|
|
31914
31979
|
supportsDelegation: market.supportsDelegation === true,
|
|
@@ -31918,11 +31983,10 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
31918
31983
|
const collNum = Number(collStr);
|
|
31919
31984
|
const debtStr = parseRawAmount(debt.toString(), loanDecimals);
|
|
31920
31985
|
const debtNum = Number(debtStr);
|
|
31921
|
-
|
|
31986
|
+
parseRawAmount(
|
|
31922
31987
|
bandBorrowed.toString(),
|
|
31923
31988
|
loanDecimals
|
|
31924
31989
|
);
|
|
31925
|
-
const bandBorrowedNum = Number(bandBorrowedStr);
|
|
31926
31990
|
const lendingPositions = {
|
|
31927
31991
|
"0": {
|
|
31928
31992
|
[collUid]: {
|
|
@@ -31944,16 +32008,18 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
31944
32008
|
[loanUid]: {
|
|
31945
32009
|
marketUid: loanUid,
|
|
31946
32010
|
underlying: loanAddr,
|
|
31947
|
-
deposits:
|
|
32011
|
+
deposits: depositStr,
|
|
31948
32012
|
debt: debtStr,
|
|
31949
32013
|
debtStable: "0",
|
|
31950
|
-
depositsUSD:
|
|
32014
|
+
depositsUSD: depositNum * loanDisplay,
|
|
31951
32015
|
debtUSD: debtNum * loanDisplay,
|
|
31952
32016
|
debtStableUSD: 0,
|
|
31953
|
-
depositsUSDOracle:
|
|
32017
|
+
depositsUSDOracle: depositNum * loanOracle,
|
|
31954
32018
|
debtUSDOracle: debtNum * loanOracle,
|
|
31955
32019
|
debtStableUSDOracle: 0,
|
|
31956
32020
|
stableBorrowRate: "0",
|
|
32021
|
+
// The borrowed token is never collateral in a LlamaLend market —
|
|
32022
|
+
// supplying it earns the lend rate, it does not back a loan.
|
|
31957
32023
|
collateralEnabled: false,
|
|
31958
32024
|
claimableRewards: 0,
|
|
31959
32025
|
llamalendInfo
|
|
@@ -31963,7 +32029,7 @@ var getLlamaLendUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
31963
32029
|
const modes = { "0": bandCount };
|
|
31964
32030
|
const hist = {
|
|
31965
32031
|
"0": {
|
|
31966
|
-
totalDeposits24h: collNum * collHist +
|
|
32032
|
+
totalDeposits24h: collNum * collHist + depositNum * loanHist,
|
|
31967
32033
|
totalDebt24h: debtNum * loanHist
|
|
31968
32034
|
}
|
|
31969
32035
|
};
|
|
@@ -32111,7 +32177,7 @@ var getResupplyUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
32111
32177
|
expected
|
|
32112
32178
|
];
|
|
32113
32179
|
};
|
|
32114
|
-
var
|
|
32180
|
+
var WAD13 = 10n ** 18n;
|
|
32115
32181
|
var big9 = (v) => {
|
|
32116
32182
|
try {
|
|
32117
32183
|
if (typeof v === "bigint") return v;
|
|
@@ -32182,7 +32248,7 @@ var getCurvanceUserDataConverter = (lender, chainId, account, meta) => {
|
|
|
32182
32248
|
const display = getDisplayPrice(rowMeta);
|
|
32183
32249
|
const oracle = getOraclePrice(rowMeta);
|
|
32184
32250
|
const histPrice = rowMeta.price?.priceUsd24h ?? display;
|
|
32185
|
-
const toUnderlying = (s) => exchangeRate > 0n ? s * exchangeRate /
|
|
32251
|
+
const toUnderlying = (s) => exchangeRate > 0n ? s * exchangeRate / WAD13 : s;
|
|
32186
32252
|
const depositsRaw = toUnderlying(collateralShares);
|
|
32187
32253
|
const depositsStr = parseRawAmount(
|
|
32188
32254
|
depositsRaw.toString(),
|
|
@@ -47118,6 +47184,416 @@ var dtrinityRebateRewardFetcher = {
|
|
|
47118
47184
|
return { byLender: merged };
|
|
47119
47185
|
}
|
|
47120
47186
|
};
|
|
47187
|
+
var SECONDS_PER_YEAR12 = 31536e3;
|
|
47188
|
+
var WAD14 = 10n ** 18n;
|
|
47189
|
+
var ZERO2 = "0x0000000000000000000000000000000000000000";
|
|
47190
|
+
var UNBOOSTED_FACTOR = 0.4;
|
|
47191
|
+
var MAX_BOOST = 2.5;
|
|
47192
|
+
var GAUGE_CONTROLLER = "0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB";
|
|
47193
|
+
var L1_CHAINS = /* @__PURE__ */ new Set([Chain.ETHEREUM_MAINNET]);
|
|
47194
|
+
var GAUGE_ABI = [
|
|
47195
|
+
{
|
|
47196
|
+
name: "inflation_rate",
|
|
47197
|
+
type: "function",
|
|
47198
|
+
stateMutability: "view",
|
|
47199
|
+
inputs: [],
|
|
47200
|
+
outputs: [{ type: "uint256" }]
|
|
47201
|
+
},
|
|
47202
|
+
{
|
|
47203
|
+
name: "working_supply",
|
|
47204
|
+
type: "function",
|
|
47205
|
+
stateMutability: "view",
|
|
47206
|
+
inputs: [],
|
|
47207
|
+
outputs: [{ type: "uint256" }]
|
|
47208
|
+
},
|
|
47209
|
+
{
|
|
47210
|
+
name: "totalSupply",
|
|
47211
|
+
type: "function",
|
|
47212
|
+
stateMutability: "view",
|
|
47213
|
+
inputs: [],
|
|
47214
|
+
outputs: [{ type: "uint256" }]
|
|
47215
|
+
},
|
|
47216
|
+
{
|
|
47217
|
+
name: "is_killed",
|
|
47218
|
+
type: "function",
|
|
47219
|
+
stateMutability: "view",
|
|
47220
|
+
inputs: [],
|
|
47221
|
+
outputs: [{ type: "bool" }]
|
|
47222
|
+
},
|
|
47223
|
+
{
|
|
47224
|
+
name: "reward_count",
|
|
47225
|
+
type: "function",
|
|
47226
|
+
stateMutability: "view",
|
|
47227
|
+
inputs: [],
|
|
47228
|
+
outputs: [{ type: "uint256" }]
|
|
47229
|
+
},
|
|
47230
|
+
{
|
|
47231
|
+
name: "reward_tokens",
|
|
47232
|
+
type: "function",
|
|
47233
|
+
stateMutability: "view",
|
|
47234
|
+
inputs: [{ type: "uint256" }],
|
|
47235
|
+
outputs: [{ type: "address" }]
|
|
47236
|
+
},
|
|
47237
|
+
{
|
|
47238
|
+
name: "reward_data",
|
|
47239
|
+
type: "function",
|
|
47240
|
+
stateMutability: "view",
|
|
47241
|
+
inputs: [{ type: "address" }],
|
|
47242
|
+
outputs: [
|
|
47243
|
+
{ name: "distributor", type: "address" },
|
|
47244
|
+
{ name: "period_finish", type: "uint256" },
|
|
47245
|
+
{ name: "rate", type: "uint256" },
|
|
47246
|
+
{ name: "last_update", type: "uint256" },
|
|
47247
|
+
{ name: "integral", type: "uint256" }
|
|
47248
|
+
]
|
|
47249
|
+
},
|
|
47250
|
+
{
|
|
47251
|
+
name: "gauge_relative_weight",
|
|
47252
|
+
type: "function",
|
|
47253
|
+
stateMutability: "view",
|
|
47254
|
+
inputs: [{ type: "address" }],
|
|
47255
|
+
outputs: [{ type: "uint256" }]
|
|
47256
|
+
},
|
|
47257
|
+
{
|
|
47258
|
+
name: "convertToAssets",
|
|
47259
|
+
type: "function",
|
|
47260
|
+
stateMutability: "view",
|
|
47261
|
+
inputs: [{ type: "uint256" }],
|
|
47262
|
+
outputs: [{ type: "uint256" }]
|
|
47263
|
+
},
|
|
47264
|
+
{
|
|
47265
|
+
name: "decimals",
|
|
47266
|
+
type: "function",
|
|
47267
|
+
stateMutability: "view",
|
|
47268
|
+
inputs: [],
|
|
47269
|
+
outputs: [{ type: "uint8" }]
|
|
47270
|
+
},
|
|
47271
|
+
{
|
|
47272
|
+
name: "symbol",
|
|
47273
|
+
type: "function",
|
|
47274
|
+
stateMutability: "view",
|
|
47275
|
+
inputs: [],
|
|
47276
|
+
outputs: [{ type: "string" }]
|
|
47277
|
+
}
|
|
47278
|
+
];
|
|
47279
|
+
var scale2 = (v, decimals) => Number(v) / 10 ** decimals;
|
|
47280
|
+
function crvGaugeApr(params) {
|
|
47281
|
+
const {
|
|
47282
|
+
inflationRate,
|
|
47283
|
+
relativeWeight,
|
|
47284
|
+
workingSupply,
|
|
47285
|
+
pricePerShare,
|
|
47286
|
+
crvPriceUsd,
|
|
47287
|
+
assetPriceUsd,
|
|
47288
|
+
isKilled
|
|
47289
|
+
} = params;
|
|
47290
|
+
if (isKilled) return 0;
|
|
47291
|
+
if (inflationRate <= 0n || relativeWeight <= 0n || workingSupply <= 0n) {
|
|
47292
|
+
return 0;
|
|
47293
|
+
}
|
|
47294
|
+
if (!(crvPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
|
|
47295
|
+
const crvPerYear = scale2(inflationRate, 18) * scale2(relativeWeight, 18) * SECONDS_PER_YEAR12;
|
|
47296
|
+
const stakedUsd = scale2(workingSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
|
|
47297
|
+
if (!(stakedUsd > 0)) return 0;
|
|
47298
|
+
return crvPerYear * crvPriceUsd / stakedUsd * 100 * UNBOOSTED_FACTOR;
|
|
47299
|
+
}
|
|
47300
|
+
function extraRewardApr(params) {
|
|
47301
|
+
const {
|
|
47302
|
+
rate,
|
|
47303
|
+
periodFinish,
|
|
47304
|
+
rewardDecimals,
|
|
47305
|
+
rewardPriceUsd,
|
|
47306
|
+
totalSupply,
|
|
47307
|
+
pricePerShare,
|
|
47308
|
+
assetPriceUsd,
|
|
47309
|
+
nowSeconds
|
|
47310
|
+
} = params;
|
|
47311
|
+
if (nowSeconds >= Number(periodFinish)) return 0;
|
|
47312
|
+
if (rate <= 0n || totalSupply <= 0n) return 0;
|
|
47313
|
+
if (!(rewardPriceUsd > 0) || !(assetPriceUsd > 0)) return 0;
|
|
47314
|
+
const rewardPerYearUsd = scale2(rate, rewardDecimals) * SECONDS_PER_YEAR12 * rewardPriceUsd;
|
|
47315
|
+
const stakedUsd = scale2(totalSupply, 18) * scale2(pricePerShare, 18) * assetPriceUsd;
|
|
47316
|
+
if (!(stakedUsd > 0)) return 0;
|
|
47317
|
+
return rewardPerYearUsd / stakedUsd * 100;
|
|
47318
|
+
}
|
|
47319
|
+
var LLAMA_CHAIN_SLUG = {
|
|
47320
|
+
[Chain.ETHEREUM_MAINNET]: "ethereum",
|
|
47321
|
+
[Chain.OP_MAINNET]: "optimism",
|
|
47322
|
+
[Chain.ARBITRUM_ONE]: "arbitrum"
|
|
47323
|
+
};
|
|
47324
|
+
async function fetchPrices(keys) {
|
|
47325
|
+
const ids = Array.from(
|
|
47326
|
+
new Set(
|
|
47327
|
+
keys.map(({ chainId, address }) => {
|
|
47328
|
+
const slug = LLAMA_CHAIN_SLUG[chainId];
|
|
47329
|
+
return slug ? `${slug}:${address.toLowerCase()}` : null;
|
|
47330
|
+
}).filter((x) => !!x)
|
|
47331
|
+
)
|
|
47332
|
+
);
|
|
47333
|
+
if (ids.length === 0) return {};
|
|
47334
|
+
const out = {};
|
|
47335
|
+
const CHUNK = 60;
|
|
47336
|
+
for (let i = 0; i < ids.length; i += CHUNK) {
|
|
47337
|
+
const slice2 = ids.slice(i, i + CHUNK);
|
|
47338
|
+
try {
|
|
47339
|
+
const res = await fetch(
|
|
47340
|
+
`https://coins.llama.fi/prices/current/${slice2.join(",")}`,
|
|
47341
|
+
{ signal: AbortSignal.timeout(1e4) }
|
|
47342
|
+
);
|
|
47343
|
+
if (!res.ok) continue;
|
|
47344
|
+
const json = await res.json();
|
|
47345
|
+
for (const [id, v] of Object.entries(json?.coins ?? {})) {
|
|
47346
|
+
if (typeof v?.price === "number") out[id.toLowerCase()] = v.price;
|
|
47347
|
+
}
|
|
47348
|
+
} catch (e) {
|
|
47349
|
+
console.error("[llamalend-gauge] price fetch failed:", e);
|
|
47350
|
+
}
|
|
47351
|
+
}
|
|
47352
|
+
return out;
|
|
47353
|
+
}
|
|
47354
|
+
var priceOf = (prices, chainId, address) => prices[`${LLAMA_CHAIN_SLUG[chainId]}:${address.toLowerCase()}`] ?? 0;
|
|
47355
|
+
function rosterFor(chainId) {
|
|
47356
|
+
const markets = llamaLendChainData(Lender.LLAMALEND, chainId)?.markets ?? [];
|
|
47357
|
+
return markets.filter((m) => m.gauge && m.gauge !== ZERO2).map((m) => ({
|
|
47358
|
+
controller: m.controller,
|
|
47359
|
+
vault: m.vault,
|
|
47360
|
+
gauge: m.gauge,
|
|
47361
|
+
borrowedToken: m.borrowedToken,
|
|
47362
|
+
name: m.name
|
|
47363
|
+
}));
|
|
47364
|
+
}
|
|
47365
|
+
var lenderKeyFor = (controller) => `${Lender.LLAMALEND}_${controller.replace(/^0x/i, "").toUpperCase()}`;
|
|
47366
|
+
async function fetchForChain(chainId, nowSeconds) {
|
|
47367
|
+
const markets = rosterFor(chainId);
|
|
47368
|
+
if (markets.length === 0) return {};
|
|
47369
|
+
const isL1 = L1_CHAINS.has(chainId);
|
|
47370
|
+
const week = BigInt(Math.floor(nowSeconds / 604800));
|
|
47371
|
+
const round1 = markets.flatMap((m) => [
|
|
47372
|
+
// L2 child gauges take the week; the L1 form takes none and reverts there.
|
|
47373
|
+
isL1 ? { address: m.gauge, name: "inflation_rate", params: [] } : { address: m.gauge, name: "inflation_rate", params: [week] },
|
|
47374
|
+
{ address: m.gauge, name: "working_supply", params: [] },
|
|
47375
|
+
{ address: m.gauge, name: "totalSupply", params: [] },
|
|
47376
|
+
{ address: m.gauge, name: "is_killed", params: [] },
|
|
47377
|
+
{ address: m.gauge, name: "reward_count", params: [] },
|
|
47378
|
+
{ address: m.vault, name: "convertToAssets", params: [WAD14] },
|
|
47379
|
+
isL1 ? {
|
|
47380
|
+
address: GAUGE_CONTROLLER,
|
|
47381
|
+
name: "gauge_relative_weight",
|
|
47382
|
+
params: [m.gauge]
|
|
47383
|
+
} : (
|
|
47384
|
+
// No gauge controller off L1; the child gauge's rate is already its own.
|
|
47385
|
+
{ address: m.gauge, name: "totalSupply", params: [] }
|
|
47386
|
+
)
|
|
47387
|
+
]);
|
|
47388
|
+
const r1 = await multicallRetryUniversal({
|
|
47389
|
+
chain: chainId,
|
|
47390
|
+
calls: round1,
|
|
47391
|
+
abi: GAUGE_ABI,
|
|
47392
|
+
allowFailure: true
|
|
47393
|
+
});
|
|
47394
|
+
const big16 = (v) => {
|
|
47395
|
+
try {
|
|
47396
|
+
if (typeof v === "bigint") return v;
|
|
47397
|
+
if (typeof v === "string" && v !== "0x") return BigInt(v);
|
|
47398
|
+
if (typeof v === "number") return BigInt(Math.trunc(v));
|
|
47399
|
+
} catch {
|
|
47400
|
+
}
|
|
47401
|
+
return 0n;
|
|
47402
|
+
};
|
|
47403
|
+
const STRIDE = 7;
|
|
47404
|
+
const state = markets.map((m, i) => {
|
|
47405
|
+
const b = i * STRIDE;
|
|
47406
|
+
return {
|
|
47407
|
+
market: m,
|
|
47408
|
+
inflationRate: big16(r1[b]),
|
|
47409
|
+
workingSupply: big16(r1[b + 1]),
|
|
47410
|
+
totalSupply: big16(r1[b + 2]),
|
|
47411
|
+
isKilled: r1[b + 3] === true,
|
|
47412
|
+
rewardCount: Number(big16(r1[b + 4])),
|
|
47413
|
+
pricePerShare: big16(r1[b + 5]),
|
|
47414
|
+
// Off L1 the child gauge's own rate is already market-scoped, so the
|
|
47415
|
+
// weight is the identity.
|
|
47416
|
+
relativeWeight: isL1 ? big16(r1[b + 6]) : WAD14
|
|
47417
|
+
};
|
|
47418
|
+
});
|
|
47419
|
+
const tokenCalls = state.flatMap(
|
|
47420
|
+
(s) => Array.from({ length: s.rewardCount }, (_3, i) => ({
|
|
47421
|
+
address: s.market.gauge,
|
|
47422
|
+
name: "reward_tokens",
|
|
47423
|
+
params: [BigInt(i)]
|
|
47424
|
+
}))
|
|
47425
|
+
);
|
|
47426
|
+
const r2 = tokenCalls.length ? await multicallRetryUniversal({
|
|
47427
|
+
chain: chainId,
|
|
47428
|
+
calls: tokenCalls,
|
|
47429
|
+
abi: GAUGE_ABI,
|
|
47430
|
+
allowFailure: true
|
|
47431
|
+
}) : [];
|
|
47432
|
+
let cursor = 0;
|
|
47433
|
+
const withTokens = state.map((s) => {
|
|
47434
|
+
const tokens = r2.slice(cursor, cursor + s.rewardCount).filter((t) => typeof t === "string" && t !== ZERO2);
|
|
47435
|
+
cursor += s.rewardCount;
|
|
47436
|
+
return { ...s, tokens };
|
|
47437
|
+
});
|
|
47438
|
+
const dataCalls = withTokens.flatMap(
|
|
47439
|
+
(s) => s.tokens.flatMap((t) => [
|
|
47440
|
+
{ address: s.market.gauge, name: "reward_data", params: [t] },
|
|
47441
|
+
{ address: t, name: "decimals", params: [] },
|
|
47442
|
+
{ address: t, name: "symbol", params: [] }
|
|
47443
|
+
])
|
|
47444
|
+
);
|
|
47445
|
+
const r3 = dataCalls.length ? await multicallRetryUniversal({
|
|
47446
|
+
chain: chainId,
|
|
47447
|
+
calls: dataCalls,
|
|
47448
|
+
abi: GAUGE_ABI,
|
|
47449
|
+
allowFailure: true
|
|
47450
|
+
}) : [];
|
|
47451
|
+
const priceKeys = [];
|
|
47452
|
+
for (const s of withTokens) {
|
|
47453
|
+
priceKeys.push({ chainId, address: s.market.borrowedToken });
|
|
47454
|
+
for (const t of s.tokens) priceKeys.push({ chainId, address: t });
|
|
47455
|
+
}
|
|
47456
|
+
const CRV_ETH = "0xD533a949740bb3306d119CC777fa900bA034cd52";
|
|
47457
|
+
if (isL1) priceKeys.push({ chainId, address: CRV_ETH });
|
|
47458
|
+
const prices = await fetchPrices(priceKeys);
|
|
47459
|
+
const crvPrice = isL1 ? priceOf(prices, chainId, CRV_ETH) : 0;
|
|
47460
|
+
const out = {};
|
|
47461
|
+
let dCursor = 0;
|
|
47462
|
+
for (const s of withTokens) {
|
|
47463
|
+
const assetPrice = priceOf(prices, chainId, s.market.borrowedToken);
|
|
47464
|
+
const streams = [];
|
|
47465
|
+
const crvApr = crvGaugeApr({
|
|
47466
|
+
inflationRate: s.inflationRate,
|
|
47467
|
+
relativeWeight: s.relativeWeight,
|
|
47468
|
+
workingSupply: s.workingSupply,
|
|
47469
|
+
pricePerShare: s.pricePerShare,
|
|
47470
|
+
crvPriceUsd: crvPrice,
|
|
47471
|
+
assetPriceUsd: assetPrice,
|
|
47472
|
+
isKilled: s.isKilled
|
|
47473
|
+
});
|
|
47474
|
+
if (crvApr > 0) {
|
|
47475
|
+
streams.push({
|
|
47476
|
+
side: "deposit",
|
|
47477
|
+
apr: crvApr,
|
|
47478
|
+
kind: "token",
|
|
47479
|
+
token: {
|
|
47480
|
+
address: CRV_ETH.toLowerCase(),
|
|
47481
|
+
symbol: "CRV",
|
|
47482
|
+
decimals: 18,
|
|
47483
|
+
priceUsd: crvPrice
|
|
47484
|
+
},
|
|
47485
|
+
source: {
|
|
47486
|
+
id: "curve:gauge-crv",
|
|
47487
|
+
label: "Curve gauge \xB7 CRV",
|
|
47488
|
+
platform: "protocol",
|
|
47489
|
+
link: `https://www.curve.finance/lend/ethereum/markets/${s.market.controller}/`,
|
|
47490
|
+
refs: {
|
|
47491
|
+
gauge: s.market.gauge,
|
|
47492
|
+
// The headline is the UNBOOSTED rate; a maxed veCRV lock earns
|
|
47493
|
+
// 2.5x it. Published so a consumer can show the range Curve does
|
|
47494
|
+
// rather than re-deriving the factor.
|
|
47495
|
+
maxBoostApr: crvApr * MAX_BOOST
|
|
47496
|
+
}
|
|
47497
|
+
},
|
|
47498
|
+
claim: "accrual"
|
|
47499
|
+
});
|
|
47500
|
+
}
|
|
47501
|
+
for (const token of s.tokens) {
|
|
47502
|
+
const data = r3[dCursor];
|
|
47503
|
+
const decRaw = r3[dCursor + 1];
|
|
47504
|
+
const symRaw = r3[dCursor + 2];
|
|
47505
|
+
dCursor += 3;
|
|
47506
|
+
if (!data) continue;
|
|
47507
|
+
const periodFinish = big16(
|
|
47508
|
+
Array.isArray(data) ? data[1] : data?.period_finish
|
|
47509
|
+
);
|
|
47510
|
+
const rate = big16(Array.isArray(data) ? data[2] : data?.rate);
|
|
47511
|
+
const decimals = typeof decRaw === "number" ? decRaw : Number(big16(decRaw) || 18n);
|
|
47512
|
+
const rewardPrice = priceOf(prices, chainId, token);
|
|
47513
|
+
const apr = extraRewardApr({
|
|
47514
|
+
rate,
|
|
47515
|
+
periodFinish,
|
|
47516
|
+
rewardDecimals: decimals,
|
|
47517
|
+
rewardPriceUsd: rewardPrice,
|
|
47518
|
+
totalSupply: s.totalSupply,
|
|
47519
|
+
pricePerShare: s.pricePerShare,
|
|
47520
|
+
assetPriceUsd: assetPrice,
|
|
47521
|
+
nowSeconds
|
|
47522
|
+
});
|
|
47523
|
+
if (apr <= 0) continue;
|
|
47524
|
+
streams.push({
|
|
47525
|
+
side: "deposit",
|
|
47526
|
+
apr,
|
|
47527
|
+
kind: "token",
|
|
47528
|
+
token: {
|
|
47529
|
+
address: token.toLowerCase(),
|
|
47530
|
+
symbol: typeof symRaw === "string" ? symRaw : void 0,
|
|
47531
|
+
decimals,
|
|
47532
|
+
priceUsd: rewardPrice
|
|
47533
|
+
},
|
|
47534
|
+
source: {
|
|
47535
|
+
id: "curve:gauge-extra",
|
|
47536
|
+
label: `Curve gauge \xB7 ${typeof symRaw === "string" ? symRaw : "reward"}`,
|
|
47537
|
+
platform: "protocol",
|
|
47538
|
+
link: `https://www.curve.finance/lend/ethereum/markets/${s.market.controller}/`,
|
|
47539
|
+
refs: { gauge: s.market.gauge, rewardToken: token }
|
|
47540
|
+
},
|
|
47541
|
+
claim: "accrual",
|
|
47542
|
+
// The whole point of carrying this: the rate survives expiry.
|
|
47543
|
+
endsAt: Number(periodFinish) || void 0
|
|
47544
|
+
});
|
|
47545
|
+
}
|
|
47546
|
+
if (streams.length === 0) continue;
|
|
47547
|
+
const deposit = streams.reduce((sum, st) => sum + st.apr, 0);
|
|
47548
|
+
const lenderKey = lenderKeyFor(s.market.controller);
|
|
47549
|
+
const asset = s.market.borrowedToken.toLowerCase();
|
|
47550
|
+
const reward = {
|
|
47551
|
+
distribution: "onchain-incentives",
|
|
47552
|
+
deposit,
|
|
47553
|
+
// Gauge rewards pay the LEND side only — the gauge stakes vault shares,
|
|
47554
|
+
// and a borrower holds none.
|
|
47555
|
+
borrow: 0,
|
|
47556
|
+
additionalDepositData: void 0,
|
|
47557
|
+
additionalBorrowData: void 0,
|
|
47558
|
+
streams
|
|
47559
|
+
};
|
|
47560
|
+
if (!out[chainId]) out[chainId] = {};
|
|
47561
|
+
if (!out[chainId][lenderKey]) out[chainId][lenderKey] = {};
|
|
47562
|
+
out[chainId][lenderKey][asset] = reward;
|
|
47563
|
+
}
|
|
47564
|
+
return out;
|
|
47565
|
+
}
|
|
47566
|
+
var GAUGE_CHAINS = [
|
|
47567
|
+
Chain.ETHEREUM_MAINNET,
|
|
47568
|
+
Chain.OP_MAINNET,
|
|
47569
|
+
Chain.ARBITRUM_ONE
|
|
47570
|
+
];
|
|
47571
|
+
var llamaLendGaugeRewardFetcher = {
|
|
47572
|
+
label: "LLAMALEND_GAUGE",
|
|
47573
|
+
// Lender-keyed: the gauge belongs to exactly one market, so there is no
|
|
47574
|
+
// deployment ambiguity to resolve against reserve tokens.
|
|
47575
|
+
fetch: async () => {
|
|
47576
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
47577
|
+
const results = await Promise.all(
|
|
47578
|
+
GAUGE_CHAINS.map(async (chainId) => {
|
|
47579
|
+
try {
|
|
47580
|
+
return await fetchForChain(chainId, nowSeconds);
|
|
47581
|
+
} catch (e) {
|
|
47582
|
+
console.error(`[llamalend-gauge] read failed on chain ${chainId}:`, e);
|
|
47583
|
+
return {};
|
|
47584
|
+
}
|
|
47585
|
+
})
|
|
47586
|
+
);
|
|
47587
|
+
const byLender = {};
|
|
47588
|
+
for (const r of results) {
|
|
47589
|
+
for (const [chainId, lenders] of Object.entries(r)) {
|
|
47590
|
+
if (!byLender[chainId]) byLender[chainId] = {};
|
|
47591
|
+
Object.assign(byLender[chainId], lenders);
|
|
47592
|
+
}
|
|
47593
|
+
}
|
|
47594
|
+
return { byLender };
|
|
47595
|
+
}
|
|
47596
|
+
};
|
|
47121
47597
|
|
|
47122
47598
|
// src/yields/rewards/fetchLenderRewards.ts
|
|
47123
47599
|
function mergeRewardResults(target, source) {
|
|
@@ -47133,7 +47609,8 @@ var rewardFetchers = [
|
|
|
47133
47609
|
aaveMerklRewardFetcher,
|
|
47134
47610
|
eulerMerklRewardFetcher,
|
|
47135
47611
|
morphoCollateralMerklRewardFetcher,
|
|
47136
|
-
dtrinityRebateRewardFetcher
|
|
47612
|
+
dtrinityRebateRewardFetcher,
|
|
47613
|
+
llamaLendGaugeRewardFetcher
|
|
47137
47614
|
];
|
|
47138
47615
|
function mergeReserveTokenRewards(target, source) {
|
|
47139
47616
|
for (const [chainId, byToken] of Object.entries(source)) {
|
|
@@ -53635,7 +54112,7 @@ query EvkByAssets($assets: [Bytes!]!) {
|
|
|
53635
54112
|
}
|
|
53636
54113
|
}
|
|
53637
54114
|
`;
|
|
53638
|
-
var
|
|
54115
|
+
var ZERO3 = 0n;
|
|
53639
54116
|
var RAY_TO_PERCENT3 = 1e25;
|
|
53640
54117
|
function readAddress2(field13) {
|
|
53641
54118
|
if (!field13) return void 0;
|
|
@@ -53650,28 +54127,28 @@ function parseVaultFee(v) {
|
|
|
53650
54127
|
return n;
|
|
53651
54128
|
}
|
|
53652
54129
|
function safeBigInt(v) {
|
|
53653
|
-
if (v == null || v === "") return
|
|
54130
|
+
if (v == null || v === "") return ZERO3;
|
|
53654
54131
|
try {
|
|
53655
54132
|
return BigInt(v);
|
|
53656
54133
|
} catch {
|
|
53657
|
-
return
|
|
54134
|
+
return ZERO3;
|
|
53658
54135
|
}
|
|
53659
54136
|
}
|
|
53660
54137
|
function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkIndex) {
|
|
53661
54138
|
if (!strategies?.length) return 0;
|
|
53662
54139
|
const totalAssets = safeBigInt(totalAssetsRaw);
|
|
53663
|
-
if (totalAssets ===
|
|
53664
|
-
let weightedRay =
|
|
54140
|
+
if (totalAssets === ZERO3) return 0;
|
|
54141
|
+
let weightedRay = ZERO3;
|
|
53665
54142
|
for (const s of strategies) {
|
|
53666
54143
|
const evk = s.strategy?.toLowerCase();
|
|
53667
54144
|
if (!evk) continue;
|
|
53668
54145
|
const apyRay = evkIndex.bySupplyApyRay.get(evk);
|
|
53669
54146
|
if (apyRay == null) continue;
|
|
53670
54147
|
const allocated = safeBigInt(s.allocatedAssets);
|
|
53671
|
-
if (allocated ===
|
|
54148
|
+
if (allocated === ZERO3) continue;
|
|
53672
54149
|
weightedRay += allocated * apyRay;
|
|
53673
54150
|
}
|
|
53674
|
-
if (weightedRay ===
|
|
54151
|
+
if (weightedRay === ZERO3) return 0;
|
|
53675
54152
|
const apyRayPerAsset = weightedRay / totalAssets;
|
|
53676
54153
|
const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
|
|
53677
54154
|
const netPercent = grossPercent * (1 - feePercent / 100);
|
|
@@ -53679,24 +54156,24 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkInd
|
|
|
53679
54156
|
}
|
|
53680
54157
|
function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
|
|
53681
54158
|
const totalAssets = safeBigInt(totalAssetsRaw);
|
|
53682
|
-
if (totalAssets ===
|
|
54159
|
+
if (totalAssets === ZERO3) return ZERO3;
|
|
53683
54160
|
if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
|
|
53684
54161
|
return totalAssets;
|
|
53685
54162
|
}
|
|
53686
54163
|
if (!strategies?.length) {
|
|
53687
54164
|
return totalAssets;
|
|
53688
54165
|
}
|
|
53689
|
-
let allocSum =
|
|
53690
|
-
let withdrawable =
|
|
54166
|
+
let allocSum = ZERO3;
|
|
54167
|
+
let withdrawable = ZERO3;
|
|
53691
54168
|
for (const s of strategies) {
|
|
53692
54169
|
const alloc = safeBigInt(s.allocatedAssets);
|
|
53693
|
-
if (alloc ===
|
|
54170
|
+
if (alloc === ZERO3) continue;
|
|
53694
54171
|
allocSum += alloc;
|
|
53695
54172
|
const evk = s.strategy?.toLowerCase();
|
|
53696
54173
|
const cash = evk ? evkIndex.byCash.get(evk) : void 0;
|
|
53697
54174
|
withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
|
|
53698
54175
|
}
|
|
53699
|
-
const idle = totalAssets > allocSum ? totalAssets - allocSum :
|
|
54176
|
+
const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO3;
|
|
53700
54177
|
const result = idle + withdrawable;
|
|
53701
54178
|
return result > totalAssets ? totalAssets : result;
|
|
53702
54179
|
}
|
|
@@ -54036,19 +54513,19 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
|
|
|
54036
54513
|
if (!address || !underlying) continue;
|
|
54037
54514
|
if (r.isEnabled === false) continue;
|
|
54038
54515
|
const assetDecimals = num4(r?.asset?.decimals) || 18;
|
|
54039
|
-
const
|
|
54516
|
+
const scale3 = 10 ** assetDecimals;
|
|
54040
54517
|
const assetEntry = tokenList[underlying];
|
|
54041
54518
|
const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(underlying, chainId);
|
|
54042
54519
|
const priceUsd = prices[priceKey];
|
|
54043
54520
|
const totalAssets = big14(r.totalAssets);
|
|
54044
54521
|
const totalSupply = big14(r.totalSupplyAmt);
|
|
54045
|
-
const totalAssetsFormatted = Number(totalAssets) /
|
|
54522
|
+
const totalAssetsFormatted = Number(totalAssets) / scale3;
|
|
54046
54523
|
const supplyRate = num4(r.apr) * 100;
|
|
54047
54524
|
const rewardsRate = num4(r?.incentiveData?.TMX_APR) * 100;
|
|
54048
54525
|
const rawLiquidity = BigInt(big14(r.redeemableAmt ?? r.idleFunds ?? "0"));
|
|
54049
54526
|
const totalAssetsBig = BigInt(totalAssets);
|
|
54050
54527
|
const liquidity = (rawLiquidity > totalAssetsBig ? totalAssetsBig : rawLiquidity).toString();
|
|
54051
|
-
const liquidityFormatted = Number(liquidity) /
|
|
54528
|
+
const liquidityFormatted = Number(liquidity) / scale3;
|
|
54052
54529
|
const totalSupplyValue = num4(r.totalSupplyValue);
|
|
54053
54530
|
out[address] = {
|
|
54054
54531
|
address,
|
|
@@ -54249,9 +54726,9 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
|
|
|
54249
54726
|
if (r.aprRaw !== void 0 && r.aprRaw > 0n) {
|
|
54250
54727
|
supplyRate = Number(r.aprRaw) / Number(DECIMAL_BASE2) * 100;
|
|
54251
54728
|
}
|
|
54252
|
-
const
|
|
54253
|
-
const totalAssetsFormatted = Number(r.totalAssets) /
|
|
54254
|
-
const liquidityFormatted = Number(idle) /
|
|
54729
|
+
const scale3 = 10 ** assetDecimals;
|
|
54730
|
+
const totalAssetsFormatted = Number(r.totalAssets) / scale3;
|
|
54731
|
+
const liquidityFormatted = Number(idle) / scale3;
|
|
54255
54732
|
const convertToAssets = r.totalSupply > 0n ? (r.totalAssets * 10n ** BigInt(r.decimals) / r.totalSupply).toString() : "0";
|
|
54256
54733
|
const entry = {
|
|
54257
54734
|
address: r.address,
|
|
@@ -55373,7 +55850,7 @@ var readerVedaAccountant = (entry) => {
|
|
|
55373
55850
|
}
|
|
55374
55851
|
};
|
|
55375
55852
|
}
|
|
55376
|
-
const
|
|
55853
|
+
const scale3 = 10n ** BigInt(18 - underlyingDec);
|
|
55377
55854
|
return {
|
|
55378
55855
|
calls: [
|
|
55379
55856
|
{ address: entry.address, name: "totalSupply", params: [] },
|
|
@@ -55384,7 +55861,7 @@ var readerVedaAccountant = (entry) => {
|
|
|
55384
55861
|
const totalSupply = toBigInt13(supply);
|
|
55385
55862
|
const rawRate = toBigInt13(rate);
|
|
55386
55863
|
if (totalSupply === void 0 || rawRate === void 0) return void 0;
|
|
55387
|
-
const exchangeRate = rawRate *
|
|
55864
|
+
const exchangeRate = rawRate * scale3;
|
|
55388
55865
|
return {
|
|
55389
55866
|
totalAssets: rescaleDecimals(
|
|
55390
55867
|
totalSupply * exchangeRate / ONE_E189,
|
|
@@ -60620,8 +61097,8 @@ var deriveTotalSupply = (totalAssetsRaw, pricePerShareRaw, decimals) => {
|
|
|
60620
61097
|
if (assets === 0n) return "0";
|
|
60621
61098
|
const pps = BigInt(pricePerShareRaw || "0");
|
|
60622
61099
|
if (pps <= 0n) return totalAssetsRaw;
|
|
60623
|
-
const
|
|
60624
|
-
return (assets *
|
|
61100
|
+
const scale3 = 10n ** BigInt(decimals);
|
|
61101
|
+
return (assets * scale3 / pps).toString();
|
|
60625
61102
|
} catch {
|
|
60626
61103
|
return totalAssetsRaw || "0";
|
|
60627
61104
|
}
|