@1delta/margin-fetcher 5.0.17 → 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.js +443 -32
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
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
|
|
@@ -20624,8 +20624,8 @@ var TermSubgraphSource = class {
|
|
|
20624
20624
|
const auction = data.termAuctions?.[0];
|
|
20625
20625
|
const clearingRate = toNum(auction?.auctionClearingPrice);
|
|
20626
20626
|
const aprPct = clearingRate > 0 ? clearingRate / WAD3 * 100 : 0;
|
|
20627
|
-
const
|
|
20628
|
-
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;
|
|
20629
20629
|
const orders = (data.termOrders ?? []).map((o) => ({
|
|
20630
20630
|
remaining: toBig3(o.originalOrderAmount) - toBig3(o.filledAmount),
|
|
20631
20631
|
isAsk: String(o.makerToken).toLowerCase() === repoToken
|
|
@@ -20714,7 +20714,7 @@ var TermSubgraphSource = class {
|
|
|
20714
20714
|
{ term, who }
|
|
20715
20715
|
);
|
|
20716
20716
|
if (!data) return null;
|
|
20717
|
-
const
|
|
20717
|
+
const scale3 = Math.pow(10, config.loanDecimals);
|
|
20718
20718
|
const toOrder = (o, side, revealedRaw) => {
|
|
20719
20719
|
const a = o.auction ?? {};
|
|
20720
20720
|
const complete = Boolean(a.auctionComplete);
|
|
@@ -20726,7 +20726,7 @@ var TermSubgraphSource = class {
|
|
|
20726
20726
|
auctionId: String(a.id ?? ""),
|
|
20727
20727
|
account,
|
|
20728
20728
|
amount: String(o.amount ?? "0"),
|
|
20729
|
-
assets: Number(toBig3(o.amount)) /
|
|
20729
|
+
assets: Number(toBig3(o.amount)) / scale3,
|
|
20730
20730
|
assignedAmount: String(o.assignedAmount ?? "0"),
|
|
20731
20731
|
locked: Boolean(o.locked),
|
|
20732
20732
|
revealed,
|
|
@@ -24552,7 +24552,7 @@ function ratePerSecToApr(rate) {
|
|
|
24552
24552
|
return Number(rate) / 1e18 * SECONDS_PER_YEAR9 * 100;
|
|
24553
24553
|
}
|
|
24554
24554
|
function buildRewardEntries(p, rsup, chainId, prices, tokens, collateralUsd, debtUsd) {
|
|
24555
|
-
const
|
|
24555
|
+
const priceOf2 = (address) => {
|
|
24556
24556
|
const lower3 = address.toLowerCase();
|
|
24557
24557
|
const token = tokens[lower3];
|
|
24558
24558
|
const key2 = toOracleKey(token?.assetGroup) || toGenericPriceKey(lower3, chainId);
|
|
@@ -24561,7 +24561,7 @@ function buildRewardEntries(p, rsup, chainId, prices, tokens, collateralUsd, deb
|
|
|
24561
24561
|
const collateral = [];
|
|
24562
24562
|
if (collateralUsd > 0) {
|
|
24563
24563
|
for (const r of p.collateralRewards ?? []) {
|
|
24564
|
-
const price2 =
|
|
24564
|
+
const price2 = priceOf2(r.token);
|
|
24565
24565
|
if (price2 <= 0) continue;
|
|
24566
24566
|
const decimals = tokens[r.token.toLowerCase()]?.decimals ?? 18;
|
|
24567
24567
|
const perSecond = Number(r.ratePerSecPerShare) * Number(p.totalCollateral ?? 0n) / 1e18;
|
|
@@ -24578,7 +24578,7 @@ function buildRewardEntries(p, rsup, chainId, prices, tokens, collateralUsd, deb
|
|
|
24578
24578
|
}
|
|
24579
24579
|
const borrow = [];
|
|
24580
24580
|
if (rsup && debtUsd > 0 && (p.rsupWeight ?? 0n) > 0n) {
|
|
24581
|
-
const price2 =
|
|
24581
|
+
const price2 = priceOf2(rsup.govToken);
|
|
24582
24582
|
if (price2 > 0) {
|
|
24583
24583
|
const decimals = tokens[rsup.govToken.toLowerCase()]?.decimals ?? 18;
|
|
24584
24584
|
const perSecond = Number(rsup.rewardRate) * Number(p.rsupWeight) / Number(rsup.totalWeight);
|
|
@@ -47184,6 +47184,416 @@ var dtrinityRebateRewardFetcher = {
|
|
|
47184
47184
|
return { byLender: merged };
|
|
47185
47185
|
}
|
|
47186
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
|
+
};
|
|
47187
47597
|
|
|
47188
47598
|
// src/yields/rewards/fetchLenderRewards.ts
|
|
47189
47599
|
function mergeRewardResults(target, source) {
|
|
@@ -47199,7 +47609,8 @@ var rewardFetchers = [
|
|
|
47199
47609
|
aaveMerklRewardFetcher,
|
|
47200
47610
|
eulerMerklRewardFetcher,
|
|
47201
47611
|
morphoCollateralMerklRewardFetcher,
|
|
47202
|
-
dtrinityRebateRewardFetcher
|
|
47612
|
+
dtrinityRebateRewardFetcher,
|
|
47613
|
+
llamaLendGaugeRewardFetcher
|
|
47203
47614
|
];
|
|
47204
47615
|
function mergeReserveTokenRewards(target, source) {
|
|
47205
47616
|
for (const [chainId, byToken] of Object.entries(source)) {
|
|
@@ -53701,7 +54112,7 @@ query EvkByAssets($assets: [Bytes!]!) {
|
|
|
53701
54112
|
}
|
|
53702
54113
|
}
|
|
53703
54114
|
`;
|
|
53704
|
-
var
|
|
54115
|
+
var ZERO3 = 0n;
|
|
53705
54116
|
var RAY_TO_PERCENT3 = 1e25;
|
|
53706
54117
|
function readAddress2(field13) {
|
|
53707
54118
|
if (!field13) return void 0;
|
|
@@ -53716,28 +54127,28 @@ function parseVaultFee(v) {
|
|
|
53716
54127
|
return n;
|
|
53717
54128
|
}
|
|
53718
54129
|
function safeBigInt(v) {
|
|
53719
|
-
if (v == null || v === "") return
|
|
54130
|
+
if (v == null || v === "") return ZERO3;
|
|
53720
54131
|
try {
|
|
53721
54132
|
return BigInt(v);
|
|
53722
54133
|
} catch {
|
|
53723
|
-
return
|
|
54134
|
+
return ZERO3;
|
|
53724
54135
|
}
|
|
53725
54136
|
}
|
|
53726
54137
|
function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkIndex) {
|
|
53727
54138
|
if (!strategies?.length) return 0;
|
|
53728
54139
|
const totalAssets = safeBigInt(totalAssetsRaw);
|
|
53729
|
-
if (totalAssets ===
|
|
53730
|
-
let weightedRay =
|
|
54140
|
+
if (totalAssets === ZERO3) return 0;
|
|
54141
|
+
let weightedRay = ZERO3;
|
|
53731
54142
|
for (const s of strategies) {
|
|
53732
54143
|
const evk = s.strategy?.toLowerCase();
|
|
53733
54144
|
if (!evk) continue;
|
|
53734
54145
|
const apyRay = evkIndex.bySupplyApyRay.get(evk);
|
|
53735
54146
|
if (apyRay == null) continue;
|
|
53736
54147
|
const allocated = safeBigInt(s.allocatedAssets);
|
|
53737
|
-
if (allocated ===
|
|
54148
|
+
if (allocated === ZERO3) continue;
|
|
53738
54149
|
weightedRay += allocated * apyRay;
|
|
53739
54150
|
}
|
|
53740
|
-
if (weightedRay ===
|
|
54151
|
+
if (weightedRay === ZERO3) return 0;
|
|
53741
54152
|
const apyRayPerAsset = weightedRay / totalAssets;
|
|
53742
54153
|
const grossPercent = apyToAprPercent(Number(apyRayPerAsset) / RAY_TO_PERCENT3);
|
|
53743
54154
|
const netPercent = grossPercent * (1 - feePercent / 100);
|
|
@@ -53745,24 +54156,24 @@ function computeWeightedSupplyApy(strategies, totalAssetsRaw, feePercent, evkInd
|
|
|
53745
54156
|
}
|
|
53746
54157
|
function computeRealLiquidity(strategies, totalAssetsRaw, evkIndex) {
|
|
53747
54158
|
const totalAssets = safeBigInt(totalAssetsRaw);
|
|
53748
|
-
if (totalAssets ===
|
|
54159
|
+
if (totalAssets === ZERO3) return ZERO3;
|
|
53749
54160
|
if (evkIndex.byCash.size === 0 && evkIndex.bySupplyApyRay.size === 0) {
|
|
53750
54161
|
return totalAssets;
|
|
53751
54162
|
}
|
|
53752
54163
|
if (!strategies?.length) {
|
|
53753
54164
|
return totalAssets;
|
|
53754
54165
|
}
|
|
53755
|
-
let allocSum =
|
|
53756
|
-
let withdrawable =
|
|
54166
|
+
let allocSum = ZERO3;
|
|
54167
|
+
let withdrawable = ZERO3;
|
|
53757
54168
|
for (const s of strategies) {
|
|
53758
54169
|
const alloc = safeBigInt(s.allocatedAssets);
|
|
53759
|
-
if (alloc ===
|
|
54170
|
+
if (alloc === ZERO3) continue;
|
|
53760
54171
|
allocSum += alloc;
|
|
53761
54172
|
const evk = s.strategy?.toLowerCase();
|
|
53762
54173
|
const cash = evk ? evkIndex.byCash.get(evk) : void 0;
|
|
53763
54174
|
withdrawable += cash == null ? alloc : alloc < cash ? alloc : cash;
|
|
53764
54175
|
}
|
|
53765
|
-
const idle = totalAssets > allocSum ? totalAssets - allocSum :
|
|
54176
|
+
const idle = totalAssets > allocSum ? totalAssets - allocSum : ZERO3;
|
|
53766
54177
|
const result = idle + withdrawable;
|
|
53767
54178
|
return result > totalAssets ? totalAssets : result;
|
|
53768
54179
|
}
|
|
@@ -54102,19 +54513,19 @@ async function fetchTermMaxVaultsFromApi(chainId, prices = {}, tokenList = {}, f
|
|
|
54102
54513
|
if (!address || !underlying) continue;
|
|
54103
54514
|
if (r.isEnabled === false) continue;
|
|
54104
54515
|
const assetDecimals = num4(r?.asset?.decimals) || 18;
|
|
54105
|
-
const
|
|
54516
|
+
const scale3 = 10 ** assetDecimals;
|
|
54106
54517
|
const assetEntry = tokenList[underlying];
|
|
54107
54518
|
const priceKey = toOracleKey(assetEntry?.assetGroup) || toGenericPriceKey(underlying, chainId);
|
|
54108
54519
|
const priceUsd = prices[priceKey];
|
|
54109
54520
|
const totalAssets = big14(r.totalAssets);
|
|
54110
54521
|
const totalSupply = big14(r.totalSupplyAmt);
|
|
54111
|
-
const totalAssetsFormatted = Number(totalAssets) /
|
|
54522
|
+
const totalAssetsFormatted = Number(totalAssets) / scale3;
|
|
54112
54523
|
const supplyRate = num4(r.apr) * 100;
|
|
54113
54524
|
const rewardsRate = num4(r?.incentiveData?.TMX_APR) * 100;
|
|
54114
54525
|
const rawLiquidity = BigInt(big14(r.redeemableAmt ?? r.idleFunds ?? "0"));
|
|
54115
54526
|
const totalAssetsBig = BigInt(totalAssets);
|
|
54116
54527
|
const liquidity = (rawLiquidity > totalAssetsBig ? totalAssetsBig : rawLiquidity).toString();
|
|
54117
|
-
const liquidityFormatted = Number(liquidity) /
|
|
54528
|
+
const liquidityFormatted = Number(liquidity) / scale3;
|
|
54118
54529
|
const totalSupplyValue = num4(r.totalSupplyValue);
|
|
54119
54530
|
out[address] = {
|
|
54120
54531
|
address,
|
|
@@ -54315,9 +54726,9 @@ var fetchTermMaxVaultsFromChain = async (chainId, multicallRetry, prices = {}, t
|
|
|
54315
54726
|
if (r.aprRaw !== void 0 && r.aprRaw > 0n) {
|
|
54316
54727
|
supplyRate = Number(r.aprRaw) / Number(DECIMAL_BASE2) * 100;
|
|
54317
54728
|
}
|
|
54318
|
-
const
|
|
54319
|
-
const totalAssetsFormatted = Number(r.totalAssets) /
|
|
54320
|
-
const liquidityFormatted = Number(idle) /
|
|
54729
|
+
const scale3 = 10 ** assetDecimals;
|
|
54730
|
+
const totalAssetsFormatted = Number(r.totalAssets) / scale3;
|
|
54731
|
+
const liquidityFormatted = Number(idle) / scale3;
|
|
54321
54732
|
const convertToAssets = r.totalSupply > 0n ? (r.totalAssets * 10n ** BigInt(r.decimals) / r.totalSupply).toString() : "0";
|
|
54322
54733
|
const entry = {
|
|
54323
54734
|
address: r.address,
|
|
@@ -55439,7 +55850,7 @@ var readerVedaAccountant = (entry) => {
|
|
|
55439
55850
|
}
|
|
55440
55851
|
};
|
|
55441
55852
|
}
|
|
55442
|
-
const
|
|
55853
|
+
const scale3 = 10n ** BigInt(18 - underlyingDec);
|
|
55443
55854
|
return {
|
|
55444
55855
|
calls: [
|
|
55445
55856
|
{ address: entry.address, name: "totalSupply", params: [] },
|
|
@@ -55450,7 +55861,7 @@ var readerVedaAccountant = (entry) => {
|
|
|
55450
55861
|
const totalSupply = toBigInt13(supply);
|
|
55451
55862
|
const rawRate = toBigInt13(rate);
|
|
55452
55863
|
if (totalSupply === void 0 || rawRate === void 0) return void 0;
|
|
55453
|
-
const exchangeRate = rawRate *
|
|
55864
|
+
const exchangeRate = rawRate * scale3;
|
|
55454
55865
|
return {
|
|
55455
55866
|
totalAssets: rescaleDecimals(
|
|
55456
55867
|
totalSupply * exchangeRate / ONE_E189,
|
|
@@ -60686,8 +61097,8 @@ var deriveTotalSupply = (totalAssetsRaw, pricePerShareRaw, decimals) => {
|
|
|
60686
61097
|
if (assets === 0n) return "0";
|
|
60687
61098
|
const pps = BigInt(pricePerShareRaw || "0");
|
|
60688
61099
|
if (pps <= 0n) return totalAssetsRaw;
|
|
60689
|
-
const
|
|
60690
|
-
return (assets *
|
|
61100
|
+
const scale3 = 10n ** BigInt(decimals);
|
|
61101
|
+
return (assets * scale3 / pps).toString();
|
|
60691
61102
|
} catch {
|
|
60692
61103
|
return totalAssetsRaw || "0";
|
|
60693
61104
|
}
|