@continuumdao/ctm-mpc-defi 0.2.1 → 0.2.2
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/agent/catalog.cjs +62 -11
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +27 -1
- package/dist/agent/catalog.js +61 -12
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/curve-dao/SKILL.md +2 -1
- package/dist/chains/evm/index.cjs +54 -0
- package/dist/chains/evm/index.cjs.map +1 -1
- package/dist/chains/evm/index.d.ts +13 -1
- package/dist/chains/evm/index.js +52 -2
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/core/index.cjs +64 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +20 -1
- package/dist/core/index.js +56 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +131 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +120 -2
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs +766 -6
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/aave-v4/index.d.ts +417 -1
- package/dist/protocols/evm/aave-v4/index.js +741 -8
- package/dist/protocols/evm/aave-v4/index.js.map +1 -1
- package/dist/protocols/evm/curve-dao/index.cjs +233 -7
- package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/curve-dao/index.d.ts +66 -1
- package/dist/protocols/evm/curve-dao/index.js +227 -9
- package/dist/protocols/evm/curve-dao/index.js.map +1 -1
- package/dist/protocols/evm/ethena/index.cjs +104 -0
- package/dist/protocols/evm/ethena/index.cjs.map +1 -1
- package/dist/protocols/evm/ethena/index.d.ts +46 -1
- package/dist/protocols/evm/ethena/index.js +99 -1
- package/dist/protocols/evm/ethena/index.js.map +1 -1
- package/dist/protocols/evm/euler-v2/index.cjs +2334 -37
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
- package/dist/protocols/evm/euler-v2/index.d.ts +464 -1
- package/dist/protocols/evm/euler-v2/index.js +2286 -39
- package/dist/protocols/evm/euler-v2/index.js.map +1 -1
- package/dist/protocols/evm/lido/index.cjs +110 -0
- package/dist/protocols/evm/lido/index.cjs.map +1 -1
- package/dist/protocols/evm/lido/index.d.ts +33 -2
- package/dist/protocols/evm/lido/index.js +107 -2
- package/dist/protocols/evm/lido/index.js.map +1 -1
- package/dist/protocols/evm/maple/index.cjs +83 -0
- package/dist/protocols/evm/maple/index.cjs.map +1 -1
- package/dist/protocols/evm/maple/index.d.ts +22 -1
- package/dist/protocols/evm/maple/index.js +82 -1
- package/dist/protocols/evm/maple/index.js.map +1 -1
- package/dist/protocols/evm/sky/index.cjs +217 -0
- package/dist/protocols/evm/sky/index.cjs.map +1 -1
- package/dist/protocols/evm/sky/index.d.ts +56 -1
- package/dist/protocols/evm/sky/index.js +210 -2
- package/dist/protocols/evm/sky/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseAbi, getAddress, defineChain, createPublicClient, http, parseUnits, encodeFunctionData, zeroAddress, maxUint256, parseGwei, serializeTransaction, keccak256 } from 'viem';
|
|
1
|
+
import { parseAbi, getAddress, defineChain, createPublicClient, http, parseUnits, encodeFunctionData, zeroAddress, maxUint256, formatUnits, isAddress, parseGwei, serializeTransaction, keccak256 } from 'viem';
|
|
2
2
|
import { fetchChainFeeParams, gasLimitFromEstimateAndChainConfig, gweiToDecimalString, proposalTxParamsToFeeSnapshot, alignEip1559FeesWithLatestBase, getClientIdFromKeyGenResult } from '@continuumdao/continuum-node-sdk';
|
|
3
3
|
|
|
4
4
|
// src/core/registry.ts
|
|
@@ -173,25 +173,25 @@ async function buildEvmMultisignBatch(args) {
|
|
|
173
173
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
174
174
|
rpcUrls: { default: { http: [rpcUrl] } }
|
|
175
175
|
});
|
|
176
|
-
const
|
|
176
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(rpcUrl) });
|
|
177
177
|
const feeParams = await fetchChainFeeParams(rpcUrl, chainId);
|
|
178
178
|
const legacy = Boolean(chainDetail?.legacy) || !feeParams.isEip1559;
|
|
179
|
-
const latestBaseFeeWei = !legacy ? (await
|
|
179
|
+
const latestBaseFeeWei = !legacy ? (await publicClient2.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
|
|
180
180
|
const gasLimitConfig = useCustomGas && chainDetail?.gasLimit != null ? Number(chainDetail.gasLimit) : void 0;
|
|
181
181
|
const chainGasLimitRouter = chainDetail?.gasLimit != null && Number.isFinite(Number(chainDetail.gasLimit)) && Number(chainDetail.gasLimit) > 0 ? Number(chainDetail.gasLimit) : void 0;
|
|
182
182
|
const gasFeeMultiplier = useCustomGas && chainDetail?.gasMultiplier != null ? Number(chainDetail.gasMultiplier) : void 0;
|
|
183
183
|
const executor = getAddress(executorAddress);
|
|
184
|
-
const baseNonce = await
|
|
184
|
+
const baseNonce = await publicClient2.getTransactionCount({ address: executor, blockTag: "pending" });
|
|
185
185
|
const legs = [];
|
|
186
186
|
for (let i = 0; i < steps.length; i++) {
|
|
187
187
|
const step = steps[i];
|
|
188
188
|
const currentNonce = baseNonce + i;
|
|
189
189
|
let estimatedGas;
|
|
190
190
|
if (args.estimateGasForStep) {
|
|
191
|
-
estimatedGas = await args.estimateGasForStep({ step, index: i, publicClient, executor });
|
|
191
|
+
estimatedGas = await args.estimateGasForStep({ step, index: i, publicClient: publicClient2, executor });
|
|
192
192
|
} else {
|
|
193
193
|
try {
|
|
194
|
-
estimatedGas = await
|
|
194
|
+
estimatedGas = await publicClient2.estimateGas({
|
|
195
195
|
to: step.to,
|
|
196
196
|
data: step.data,
|
|
197
197
|
value: step.value,
|
|
@@ -203,7 +203,7 @@ async function buildEvmMultisignBatch(args) {
|
|
|
203
203
|
}
|
|
204
204
|
let gasLimitI;
|
|
205
205
|
if (args.resolveGasLimit) {
|
|
206
|
-
gasLimitI = await args.resolveGasLimit({ step, index: i, estimatedGas, publicClient });
|
|
206
|
+
gasLimitI = await args.resolveGasLimit({ step, index: i, estimatedGas, publicClient: publicClient2 });
|
|
207
207
|
} else if (step.routerSwap) {
|
|
208
208
|
gasLimitI = routerSwapGasLimitFromEstimate(estimatedGas, chainGasLimitRouter);
|
|
209
209
|
} else {
|
|
@@ -213,7 +213,7 @@ async function buildEvmMultisignBatch(args) {
|
|
|
213
213
|
let feeSnapshot;
|
|
214
214
|
let serialized;
|
|
215
215
|
if (legacy) {
|
|
216
|
-
let gasPriceWei = await
|
|
216
|
+
let gasPriceWei = await publicClient2.getGasPrice();
|
|
217
217
|
if (useCustomGas && gasFeeMultiplier != null && gasFeeMultiplier > 0) {
|
|
218
218
|
gasPriceWei = gasPriceWei * BigInt(100 + gasFeeMultiplier) / 100n;
|
|
219
219
|
}
|
|
@@ -331,14 +331,14 @@ async function fetchEulerVaultUnderlyingMeta(args) {
|
|
|
331
331
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
332
332
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
333
333
|
});
|
|
334
|
-
const
|
|
335
|
-
const assetAddrRaw = await
|
|
334
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
335
|
+
const assetAddrRaw = await publicClient2.readContract({
|
|
336
336
|
address: args.evault,
|
|
337
337
|
abi: erc4626AssetAbi,
|
|
338
338
|
functionName: "asset"
|
|
339
339
|
});
|
|
340
340
|
const assetAddr = getAddress(assetAddrRaw);
|
|
341
|
-
const d = await
|
|
341
|
+
const d = await publicClient2.readContract({
|
|
342
342
|
address: assetAddr,
|
|
343
343
|
abi: erc20DecimalsAbi,
|
|
344
344
|
functionName: "decimals"
|
|
@@ -370,8 +370,8 @@ async function fetchEulerVaultMaxWithdrawWei(args) {
|
|
|
370
370
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
371
371
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
372
372
|
});
|
|
373
|
-
const
|
|
374
|
-
return
|
|
373
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
374
|
+
return publicClient2.readContract({
|
|
375
375
|
address: args.evault,
|
|
376
376
|
abi: erc4626MaxWithdrawAbi,
|
|
377
377
|
functionName: "maxWithdraw",
|
|
@@ -408,19 +408,19 @@ async function eulerLendEarnEffectiveMaxWeiBySimulation(args) {
|
|
|
408
408
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
409
409
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
410
410
|
});
|
|
411
|
-
const
|
|
411
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
412
412
|
let shareBal;
|
|
413
413
|
let vaultCash;
|
|
414
414
|
try {
|
|
415
415
|
;
|
|
416
416
|
[shareBal, vaultCash] = await Promise.all([
|
|
417
|
-
|
|
417
|
+
publicClient2.readContract({
|
|
418
418
|
address: args.evault,
|
|
419
419
|
abi: eulerVaultSharesCashAbi,
|
|
420
420
|
functionName: "balanceOf",
|
|
421
421
|
args: [args.vaultShareOwner]
|
|
422
422
|
}),
|
|
423
|
-
|
|
423
|
+
publicClient2.readContract({
|
|
424
424
|
address: args.evault,
|
|
425
425
|
abi: eulerVaultSharesCashAbi,
|
|
426
426
|
functionName: "cash"
|
|
@@ -432,7 +432,7 @@ async function eulerLendEarnEffectiveMaxWeiBySimulation(args) {
|
|
|
432
432
|
if (shareBal === 0n) return 0n;
|
|
433
433
|
let assetsOwned;
|
|
434
434
|
try {
|
|
435
|
-
assetsOwned = await
|
|
435
|
+
assetsOwned = await publicClient2.readContract({
|
|
436
436
|
address: args.evault,
|
|
437
437
|
abi: eulerVaultSharesCashAbi,
|
|
438
438
|
functionName: "convertToAssets",
|
|
@@ -449,7 +449,7 @@ async function eulerLendEarnEffectiveMaxWeiBySimulation(args) {
|
|
|
449
449
|
while (lo <= hiProbe) {
|
|
450
450
|
const mid = lo + (hiProbe - lo) / 2n;
|
|
451
451
|
const ok = await eulerDirectWithdrawSimulatesOk({
|
|
452
|
-
publicClient,
|
|
452
|
+
publicClient: publicClient2,
|
|
453
453
|
evault: args.evault,
|
|
454
454
|
vaultShareOwner: args.vaultShareOwner,
|
|
455
455
|
receiver: args.receiver,
|
|
@@ -612,20 +612,20 @@ async function collateralMaxWithdrawBySimulation(args) {
|
|
|
612
612
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
613
613
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
614
614
|
});
|
|
615
|
-
const
|
|
615
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
616
616
|
let shareBal;
|
|
617
617
|
let assetsOwned;
|
|
618
618
|
let vaultCash;
|
|
619
619
|
try {
|
|
620
620
|
;
|
|
621
621
|
[shareBal, vaultCash] = await Promise.all([
|
|
622
|
-
|
|
622
|
+
publicClient2.readContract({
|
|
623
623
|
address: args.collateralVault,
|
|
624
624
|
abi: eulerCollateralVaultReadAbi,
|
|
625
625
|
functionName: "balanceOf",
|
|
626
626
|
args: [args.subAccount]
|
|
627
627
|
}),
|
|
628
|
-
|
|
628
|
+
publicClient2.readContract({
|
|
629
629
|
address: args.collateralVault,
|
|
630
630
|
abi: eulerCollateralVaultReadAbi,
|
|
631
631
|
functionName: "cash"
|
|
@@ -636,7 +636,7 @@ async function collateralMaxWithdrawBySimulation(args) {
|
|
|
636
636
|
}
|
|
637
637
|
if (shareBal === 0n) return 0n;
|
|
638
638
|
try {
|
|
639
|
-
assetsOwned = await
|
|
639
|
+
assetsOwned = await publicClient2.readContract({
|
|
640
640
|
address: args.collateralVault,
|
|
641
641
|
abi: eulerCollateralVaultReadAbi,
|
|
642
642
|
functionName: "convertToAssets",
|
|
@@ -653,7 +653,7 @@ async function collateralMaxWithdrawBySimulation(args) {
|
|
|
653
653
|
while (lo <= hiProbe) {
|
|
654
654
|
const mid = lo + (hiProbe - lo) / 2n;
|
|
655
655
|
const ok = await evcWithdrawSimulatesOk({
|
|
656
|
-
publicClient,
|
|
656
|
+
publicClient: publicClient2,
|
|
657
657
|
evc: args.evc,
|
|
658
658
|
collateralVault: args.collateralVault,
|
|
659
659
|
subAccount: args.subAccount,
|
|
@@ -720,8 +720,8 @@ async function buildEvmMultisignBodyEulerV2IsolatedLendDepositBatch(args) {
|
|
|
720
720
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
721
721
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
722
722
|
});
|
|
723
|
-
const
|
|
724
|
-
const dec = await
|
|
723
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
724
|
+
const dec = await publicClient2.readContract({
|
|
725
725
|
address: asset,
|
|
726
726
|
abi: erc20AllowanceAbi,
|
|
727
727
|
functionName: "decimals"
|
|
@@ -732,7 +732,7 @@ async function buildEvmMultisignBodyEulerV2IsolatedLendDepositBatch(args) {
|
|
|
732
732
|
if (args.isNativeIn) {
|
|
733
733
|
const dataDeposit = encodeFunctionData({ abi: wethDepositAbi, functionName: "deposit", args: [] });
|
|
734
734
|
steps.push({ kind: "weth_deposit", to: weth, data: dataDeposit, value: amountWei });
|
|
735
|
-
const wethAllowance = await
|
|
735
|
+
const wethAllowance = await publicClient2.readContract({
|
|
736
736
|
address: weth,
|
|
737
737
|
abi: erc20AllowanceAbi,
|
|
738
738
|
functionName: "allowance",
|
|
@@ -755,7 +755,7 @@ async function buildEvmMultisignBodyEulerV2IsolatedLendDepositBatch(args) {
|
|
|
755
755
|
steps.push({ kind: "approve", to: weth, data: dataApprove, value: 0n });
|
|
756
756
|
}
|
|
757
757
|
} else {
|
|
758
|
-
const currentAllowance = await
|
|
758
|
+
const currentAllowance = await publicClient2.readContract({
|
|
759
759
|
address: asset,
|
|
760
760
|
abi: erc20AllowanceAbi,
|
|
761
761
|
functionName: "allowance",
|
|
@@ -915,8 +915,8 @@ async function buildEvmMultisignBodyEulerV2IsolatedBorrowBatch(args) {
|
|
|
915
915
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
916
916
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
917
917
|
});
|
|
918
|
-
const
|
|
919
|
-
const cDecRaw = await
|
|
918
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
919
|
+
const cDecRaw = await publicClient2.readContract({
|
|
920
920
|
address: collateralAsset,
|
|
921
921
|
abi: erc20AllowanceAbi2,
|
|
922
922
|
functionName: "decimals"
|
|
@@ -924,7 +924,7 @@ async function buildEvmMultisignBodyEulerV2IsolatedBorrowBatch(args) {
|
|
|
924
924
|
const collateralDecimals = Number(cDecRaw);
|
|
925
925
|
const collateralWei = parseUnits(args.collateralAmountHuman, collateralDecimals);
|
|
926
926
|
if (collateralWei === 0n) throw new Error("Collateral amount is zero after converting with token decimals.");
|
|
927
|
-
await
|
|
927
|
+
await publicClient2.readContract({
|
|
928
928
|
address: borrowAsset,
|
|
929
929
|
abi: erc20AllowanceAbi2,
|
|
930
930
|
functionName: "decimals"
|
|
@@ -947,7 +947,7 @@ async function buildEvmMultisignBodyEulerV2IsolatedBorrowBatch(args) {
|
|
|
947
947
|
if (args.isNativeCollateralIn) {
|
|
948
948
|
const dataDeposit = encodeFunctionData({ abi: wethDepositAbi2, functionName: "deposit", args: [] });
|
|
949
949
|
steps.push({ kind: "weth_deposit", to: weth, data: dataDeposit, value: collateralWei });
|
|
950
|
-
const wethAllowance = await
|
|
950
|
+
const wethAllowance = await publicClient2.readContract({
|
|
951
951
|
address: weth,
|
|
952
952
|
abi: erc20AllowanceAbi2,
|
|
953
953
|
functionName: "allowance",
|
|
@@ -970,7 +970,7 @@ async function buildEvmMultisignBodyEulerV2IsolatedBorrowBatch(args) {
|
|
|
970
970
|
steps.push({ kind: "approve", to: weth, data: dataApprove, value: 0n });
|
|
971
971
|
}
|
|
972
972
|
} else {
|
|
973
|
-
const currentAllowance = await
|
|
973
|
+
const currentAllowance = await publicClient2.readContract({
|
|
974
974
|
address: collateralAsset,
|
|
975
975
|
abi: erc20AllowanceAbi2,
|
|
976
976
|
functionName: "allowance",
|
|
@@ -1167,15 +1167,15 @@ async function buildEvmMultisignBodyEulerV2BorrowRepayBatch(args) {
|
|
|
1167
1167
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
1168
1168
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
1169
1169
|
});
|
|
1170
|
-
const
|
|
1171
|
-
const bDecRaw = await
|
|
1170
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
1171
|
+
const bDecRaw = await publicClient2.readContract({
|
|
1172
1172
|
address: borrowAsset,
|
|
1173
1173
|
abi: erc20AllowanceAbi3,
|
|
1174
1174
|
functionName: "decimals"
|
|
1175
1175
|
});
|
|
1176
1176
|
const borrowDecimals = Number(bDecRaw);
|
|
1177
1177
|
const debtAbi = parseAbi(["function debtOf(address account) view returns (uint256)"]);
|
|
1178
|
-
const owed = await
|
|
1178
|
+
const owed = await publicClient2.readContract({
|
|
1179
1179
|
address: borrowVault,
|
|
1180
1180
|
abi: debtAbi,
|
|
1181
1181
|
functionName: "debtOf",
|
|
@@ -1193,7 +1193,7 @@ async function buildEvmMultisignBodyEulerV2BorrowRepayBatch(args) {
|
|
|
1193
1193
|
}
|
|
1194
1194
|
const steps = [];
|
|
1195
1195
|
const allowanceTarget = repayWei === maxUint256 ? owed : repayWei;
|
|
1196
|
-
const currentAllowance = await
|
|
1196
|
+
const currentAllowance = await publicClient2.readContract({
|
|
1197
1197
|
address: borrowAsset,
|
|
1198
1198
|
abi: erc20AllowanceAbi3,
|
|
1199
1199
|
functionName: "allowance",
|
|
@@ -1321,7 +1321,7 @@ async function buildEvmMultisignBodyEulerV2BorrowCollateralDepositBatch(args) {
|
|
|
1321
1321
|
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
1322
1322
|
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
1323
1323
|
});
|
|
1324
|
-
const
|
|
1324
|
+
const publicClient2 = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
1325
1325
|
const dec = await fetchEulerVaultAssetDecimals({
|
|
1326
1326
|
rpcUrl: args.rpcUrl,
|
|
1327
1327
|
chainId: args.chainId,
|
|
@@ -1330,7 +1330,7 @@ async function buildEvmMultisignBodyEulerV2BorrowCollateralDepositBatch(args) {
|
|
|
1330
1330
|
const amountWei = parseUnits(args.amountHuman, dec);
|
|
1331
1331
|
if (amountWei === 0n) throw new Error("Deposit amount is zero after converting with token decimals.");
|
|
1332
1332
|
const steps = [];
|
|
1333
|
-
const currentAllowance = await
|
|
1333
|
+
const currentAllowance = await publicClient2.readContract({
|
|
1334
1334
|
address: collateralAsset,
|
|
1335
1335
|
abi: erc20AllowanceAbi4,
|
|
1336
1336
|
functionName: "allowance",
|
|
@@ -1533,6 +1533,2253 @@ async function buildEvmMultisignBodyEulerV2BorrowCollateralWithdrawBatch(args) {
|
|
|
1533
1533
|
});
|
|
1534
1534
|
}
|
|
1535
1535
|
|
|
1536
|
+
// src/core/defiProxy.ts
|
|
1537
|
+
var aaveGraphqlProxyUrl;
|
|
1538
|
+
var eulerGraphqlProxyUrl;
|
|
1539
|
+
var coingeckoProxyUrl;
|
|
1540
|
+
function getAaveGraphqlProxyUrl() {
|
|
1541
|
+
return aaveGraphqlProxyUrl;
|
|
1542
|
+
}
|
|
1543
|
+
function getEulerGraphqlProxyUrl() {
|
|
1544
|
+
return eulerGraphqlProxyUrl;
|
|
1545
|
+
}
|
|
1546
|
+
function getCoingeckoProxyUrl() {
|
|
1547
|
+
return coingeckoProxyUrl;
|
|
1548
|
+
}
|
|
1549
|
+
async function postJsonViaOptionalProxy(args) {
|
|
1550
|
+
const proxy = args.proxyUrl?.trim();
|
|
1551
|
+
if (proxy) {
|
|
1552
|
+
const r2 = await fetch(proxy, {
|
|
1553
|
+
method: "POST",
|
|
1554
|
+
headers: { "content-type": "application/json" },
|
|
1555
|
+
body: JSON.stringify(args.proxyEnvelope ?? args.body)
|
|
1556
|
+
});
|
|
1557
|
+
if (!r2.ok) {
|
|
1558
|
+
const t = await r2.text().catch(() => "");
|
|
1559
|
+
throw new Error(t ? `Proxy HTTP ${r2.status}: ${t.slice(0, 200)}` : `Proxy HTTP ${r2.status}`);
|
|
1560
|
+
}
|
|
1561
|
+
return await r2.json();
|
|
1562
|
+
}
|
|
1563
|
+
const r = await fetch(args.directUrl, {
|
|
1564
|
+
method: "POST",
|
|
1565
|
+
headers: { "content-type": "application/json" },
|
|
1566
|
+
body: JSON.stringify(args.body)
|
|
1567
|
+
});
|
|
1568
|
+
if (!r.ok) {
|
|
1569
|
+
const t = await r.text().catch(() => "");
|
|
1570
|
+
throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`);
|
|
1571
|
+
}
|
|
1572
|
+
return await r.json();
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
// src/protocols/evm/aave-v4/api.ts
|
|
1576
|
+
var AAVE_V4_GRAPHQL_URL = "https://api.v4.aave.com/graphql";
|
|
1577
|
+
async function aaveV4Gql(query, variables) {
|
|
1578
|
+
const body = { query, variables: variables ?? {} };
|
|
1579
|
+
const j = await postJsonViaOptionalProxy({
|
|
1580
|
+
directUrl: AAVE_V4_GRAPHQL_URL,
|
|
1581
|
+
body,
|
|
1582
|
+
proxyUrl: getAaveGraphqlProxyUrl(),
|
|
1583
|
+
proxyEnvelope: body
|
|
1584
|
+
});
|
|
1585
|
+
if (j.errors?.length) {
|
|
1586
|
+
const msg = j.errors.map((e) => e.message ?? "Unknown").join("; ");
|
|
1587
|
+
throw new Error(msg);
|
|
1588
|
+
}
|
|
1589
|
+
if (j.data == null) {
|
|
1590
|
+
throw new Error("Aave V4 API: empty response");
|
|
1591
|
+
}
|
|
1592
|
+
return j.data;
|
|
1593
|
+
}
|
|
1594
|
+
async function fetchAaveV4Chains() {
|
|
1595
|
+
const d = await aaveV4Gql(`
|
|
1596
|
+
query C($c: ChainsRequest!) { chains(request: $c) { chainId name nativeWrappedToken } }
|
|
1597
|
+
`, { c: { query: { filter: "ALL" } } });
|
|
1598
|
+
return d.chains ?? [];
|
|
1599
|
+
}
|
|
1600
|
+
async function fetchAaveV4NativeWrappedToken(chainId) {
|
|
1601
|
+
const all = await fetchAaveV4Chains();
|
|
1602
|
+
const c = all.find((x) => x.chainId === chainId);
|
|
1603
|
+
const t = (c?.nativeWrappedToken ?? "").trim();
|
|
1604
|
+
if (t && isAddress(t)) return getAddress(t);
|
|
1605
|
+
return null;
|
|
1606
|
+
}
|
|
1607
|
+
var EULER_EVAULT_CAP_UNLIMITED_WEI = (1n << 256n) - 1n;
|
|
1608
|
+
var UINT256_MAX = EULER_EVAULT_CAP_UNLIMITED_WEI;
|
|
1609
|
+
var EULER_EVAULT_SUPPLY_CAP_UNLIMITED_WEI = EULER_EVAULT_CAP_UNLIMITED_WEI;
|
|
1610
|
+
var EULER_V2_PREFER_ON_CHAIN_LEND_METRICS = false;
|
|
1611
|
+
var eulerVaultLendAbi = parseAbi([
|
|
1612
|
+
"function caps() view returns (uint16 supplyCap, uint16 borrowCap)",
|
|
1613
|
+
"function cash() view returns (uint256)",
|
|
1614
|
+
"function totalBorrows() view returns (uint256)",
|
|
1615
|
+
"function totalAssets() view returns (uint256)"
|
|
1616
|
+
]);
|
|
1617
|
+
function resolveEulerAmountCapToWei(rawCap16) {
|
|
1618
|
+
const amountCap = BigInt(rawCap16) & 0xffffn;
|
|
1619
|
+
if (amountCap === 0n) return UINT256_MAX;
|
|
1620
|
+
const exp = amountCap & 63n;
|
|
1621
|
+
const mantissa = amountCap >> 6n;
|
|
1622
|
+
return 10n ** exp * mantissa / 100n;
|
|
1623
|
+
}
|
|
1624
|
+
var resolveEulerAmountCapToSupplyWei = resolveEulerAmountCapToWei;
|
|
1625
|
+
function eulerSubgraphVaultCapToUnderlyingWei(raw) {
|
|
1626
|
+
try {
|
|
1627
|
+
const v = BigInt((raw ?? "").trim() || "0");
|
|
1628
|
+
if (v >= UINT256_MAX - 3n) return v;
|
|
1629
|
+
if (v <= 0xffffn) return resolveEulerAmountCapToWei(v);
|
|
1630
|
+
return v;
|
|
1631
|
+
} catch {
|
|
1632
|
+
return 0n;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
function eulerVaultLendMetricsFromIndexerVaultState(args) {
|
|
1636
|
+
let rawSupplyCap16 = 0;
|
|
1637
|
+
let rawBorrowCap16 = 0;
|
|
1638
|
+
try {
|
|
1639
|
+
rawSupplyCap16 = Number(BigInt((args.supplyCapRaw ?? "").trim() || "0") & 0xffffn);
|
|
1640
|
+
} catch {
|
|
1641
|
+
rawSupplyCap16 = 0;
|
|
1642
|
+
}
|
|
1643
|
+
try {
|
|
1644
|
+
rawBorrowCap16 = Number(BigInt((args.borrowCapRaw ?? "").trim() || "0") & 0xffffn);
|
|
1645
|
+
} catch {
|
|
1646
|
+
rawBorrowCap16 = 0;
|
|
1647
|
+
}
|
|
1648
|
+
return {
|
|
1649
|
+
rawSupplyCap16,
|
|
1650
|
+
rawBorrowCap16,
|
|
1651
|
+
supplyCapWei: eulerSubgraphVaultCapToUnderlyingWei(args.supplyCapRaw),
|
|
1652
|
+
borrowCapWei: eulerSubgraphVaultCapToUnderlyingWei(args.borrowCapRaw),
|
|
1653
|
+
cashWei: args.cashWei,
|
|
1654
|
+
totalBorrowsWei: args.totalBorrowsWei,
|
|
1655
|
+
totalAssetsWei: args.totalAssetsWei
|
|
1656
|
+
};
|
|
1657
|
+
}
|
|
1658
|
+
function formatEulerResolvedCapOrCashForUi(wei, decimals, symbolSuffix) {
|
|
1659
|
+
if (wei >= EULER_EVAULT_CAP_UNLIMITED_WEI - 3n) return "Unlimited";
|
|
1660
|
+
if (wei === 0n) return symbolSuffix ? `0 ${symbolSuffix}` : "0";
|
|
1661
|
+
try {
|
|
1662
|
+
const s = formatUnits(wei, decimals);
|
|
1663
|
+
const n = Number(s);
|
|
1664
|
+
if (Number.isFinite(n) && Math.abs(n) >= 1e9) return `${n.toExponential(2)}${symbolSuffix ? ` ${symbolSuffix}` : ""}`;
|
|
1665
|
+
return symbolSuffix ? `${s} ${symbolSuffix}` : s;
|
|
1666
|
+
} catch {
|
|
1667
|
+
return wei.toString();
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
function eulerVaultMaxNewSupplyWei(metrics) {
|
|
1671
|
+
const { supplyCapWei, totalAssetsWei } = metrics;
|
|
1672
|
+
if (supplyCapWei === 0n) return 0n;
|
|
1673
|
+
if (supplyCapWei >= EULER_EVAULT_CAP_UNLIMITED_WEI - 3n) return EULER_EVAULT_CAP_UNLIMITED_WEI;
|
|
1674
|
+
if (totalAssetsWei >= supplyCapWei) return 0n;
|
|
1675
|
+
return supplyCapWei - totalAssetsWei;
|
|
1676
|
+
}
|
|
1677
|
+
function eulerVaultMaxNewBorrowWei(metrics) {
|
|
1678
|
+
const { cashWei, borrowCapWei, totalBorrowsWei } = metrics;
|
|
1679
|
+
if (borrowCapWei === 0n) return 0n;
|
|
1680
|
+
if (borrowCapWei >= EULER_EVAULT_CAP_UNLIMITED_WEI - 3n) return cashWei;
|
|
1681
|
+
const capLeft = borrowCapWei > totalBorrowsWei ? borrowCapWei - totalBorrowsWei : 0n;
|
|
1682
|
+
return cashWei < capLeft ? cashWei : capLeft;
|
|
1683
|
+
}
|
|
1684
|
+
async function fetchEulerVaultOnChainLendMetrics(args) {
|
|
1685
|
+
const ch = defineChain({
|
|
1686
|
+
id: args.chainId,
|
|
1687
|
+
name: "EulerVaultRead",
|
|
1688
|
+
nativeCurrency: { decimals: 18, name: "x", symbol: "x" },
|
|
1689
|
+
rpcUrls: { default: { http: [args.rpcUrl] } }
|
|
1690
|
+
});
|
|
1691
|
+
const client = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
|
|
1692
|
+
const addr = getAddress(args.evault);
|
|
1693
|
+
const [[supplyRaw, borrowRaw], cashWei, totalBorrowsWei, totalAssetsWei] = await Promise.all([
|
|
1694
|
+
client.readContract({
|
|
1695
|
+
address: addr,
|
|
1696
|
+
abi: eulerVaultLendAbi,
|
|
1697
|
+
functionName: "caps"
|
|
1698
|
+
}),
|
|
1699
|
+
client.readContract({
|
|
1700
|
+
address: addr,
|
|
1701
|
+
abi: eulerVaultLendAbi,
|
|
1702
|
+
functionName: "cash"
|
|
1703
|
+
}),
|
|
1704
|
+
client.readContract({
|
|
1705
|
+
address: addr,
|
|
1706
|
+
abi: eulerVaultLendAbi,
|
|
1707
|
+
functionName: "totalBorrows"
|
|
1708
|
+
}),
|
|
1709
|
+
client.readContract({
|
|
1710
|
+
address: addr,
|
|
1711
|
+
abi: eulerVaultLendAbi,
|
|
1712
|
+
functionName: "totalAssets"
|
|
1713
|
+
})
|
|
1714
|
+
]);
|
|
1715
|
+
const rs = Number(supplyRaw);
|
|
1716
|
+
const rb = Number(borrowRaw);
|
|
1717
|
+
return {
|
|
1718
|
+
rawSupplyCap16: rs,
|
|
1719
|
+
rawBorrowCap16: rb,
|
|
1720
|
+
supplyCapWei: resolveEulerAmountCapToWei(rs),
|
|
1721
|
+
borrowCapWei: resolveEulerAmountCapToWei(rb),
|
|
1722
|
+
cashWei,
|
|
1723
|
+
totalBorrowsWei,
|
|
1724
|
+
totalAssetsWei
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
async function fetchEulerVaultOnChainLendMetricsForVaults(args) {
|
|
1728
|
+
const rpc = (args.rpcUrl ?? "").trim();
|
|
1729
|
+
const out = /* @__PURE__ */ new Map();
|
|
1730
|
+
if (!rpc || !args.vaults.length) return out;
|
|
1731
|
+
const concurrency = 8;
|
|
1732
|
+
let idx = 0;
|
|
1733
|
+
const list = [...args.vaults];
|
|
1734
|
+
async function worker() {
|
|
1735
|
+
while (idx < list.length) {
|
|
1736
|
+
const i = idx++;
|
|
1737
|
+
const row = list[i];
|
|
1738
|
+
try {
|
|
1739
|
+
const ev = getAddress(row.evault.trim());
|
|
1740
|
+
const data = await fetchEulerVaultOnChainLendMetrics({
|
|
1741
|
+
rpcUrl: rpc,
|
|
1742
|
+
chainId: args.chainId,
|
|
1743
|
+
evault: ev
|
|
1744
|
+
});
|
|
1745
|
+
out.set(row.key, { ok: true, data });
|
|
1746
|
+
} catch (e) {
|
|
1747
|
+
out.set(row.key, {
|
|
1748
|
+
ok: false,
|
|
1749
|
+
message: e instanceof Error ? e.message : "On-chain read failed"
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, list.length) }, () => worker()));
|
|
1755
|
+
return out;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
// src/protocols/evm/euler-v2/eulerV2Subgraph.ts
|
|
1759
|
+
var EULER_V2_GOLDSKY_SUBGRAPH_URL_BY_CHAIN_ID = {
|
|
1760
|
+
1: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-mainnet/latest/gn",
|
|
1761
|
+
8453: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-base/latest/gn",
|
|
1762
|
+
1923: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-swell/latest/gn",
|
|
1763
|
+
146: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-sonic/latest/gn",
|
|
1764
|
+
60808: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-bob/latest/gn",
|
|
1765
|
+
80094: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-berachain/latest/gn",
|
|
1766
|
+
43114: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-avalanche/latest/gn",
|
|
1767
|
+
42161: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-arbitrum/latest/gn",
|
|
1768
|
+
130: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-unichain/latest/gn",
|
|
1769
|
+
57073: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-ink/latest/gn",
|
|
1770
|
+
56: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-bsc/latest/gn",
|
|
1771
|
+
999: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-hyperevm/latest/gn",
|
|
1772
|
+
10: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-optimism/latest/gn",
|
|
1773
|
+
100: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-gnosis/latest/gn",
|
|
1774
|
+
480: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-worldchain/latest/gn",
|
|
1775
|
+
239: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-tac/latest/gn",
|
|
1776
|
+
9745: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-plasma/latest/gn",
|
|
1777
|
+
5e3: "https://api.goldsky.com/api/public/project_cm4iagnemt1wp01xn4gh1agft/subgraphs/euler-v2-mantle/latest/gn"
|
|
1778
|
+
};
|
|
1779
|
+
var WRAPPED_NATIVE_FALLBACK = {
|
|
1780
|
+
1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
1781
|
+
10: "0x4200000000000000000000000000000000000006",
|
|
1782
|
+
56: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
|
|
1783
|
+
100: "0xe91d153e0b41518a2ce8dd3d7944fa863463a97d",
|
|
1784
|
+
130: "0x4200000000000000000000000000000000000006",
|
|
1785
|
+
146: "0x03980325872071166574bcd94670450917897468",
|
|
1786
|
+
239: "0xB63B9f0eb4A6E6f191529D71d4D88cc8900Df2C9",
|
|
1787
|
+
// TAC: WTAC (https://docs.tac.build/ecosystem/token-list)
|
|
1788
|
+
480: "0x4200000000000000000000000000000000000006",
|
|
1789
|
+
999: "0x5555555555555555555555555555555555555555",
|
|
1790
|
+
// HyperEVM: WHYPE (Hyperliquid docs)
|
|
1791
|
+
1923: "0x4200000000000000000000000000000000000006",
|
|
1792
|
+
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
1793
|
+
43114: "0xB31f66AA3C1e785363F0875A1B74D27b85FE0459",
|
|
1794
|
+
5e3: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8",
|
|
1795
|
+
// Mantle: WMNT
|
|
1796
|
+
57073: "0x4200000000000000000000000000000000000006",
|
|
1797
|
+
60808: "0x4200000000000000000000000000000000000006",
|
|
1798
|
+
80094: "0x6969696969696969696969696969696969696969",
|
|
1799
|
+
// Berachain: WBERA (https://docs.berachain.com)
|
|
1800
|
+
8453: "0x4200000000000000000000000000000000000006",
|
|
1801
|
+
9745: "0x6100E367285b01F48D07953803A2d8dCA5D19873"
|
|
1802
|
+
// Plasma: WXPL
|
|
1803
|
+
};
|
|
1804
|
+
for (const id of Object.keys(EULER_V2_GOLDSKY_SUBGRAPH_URL_BY_CHAIN_ID).map(Number)) {
|
|
1805
|
+
if (WRAPPED_NATIVE_FALLBACK[id] == null) {
|
|
1806
|
+
throw new Error(`eulerV2Subgraph: add WRAPPED_NATIVE_FALLBACK for Euler Goldsky chain ${id}`);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
function eulerV2GoldskyUrlForChain(chainId) {
|
|
1810
|
+
return EULER_V2_GOLDSKY_SUBGRAPH_URL_BY_CHAIN_ID[chainId];
|
|
1811
|
+
}
|
|
1812
|
+
async function resolveEulerWrappedNativeToken(chainId) {
|
|
1813
|
+
try {
|
|
1814
|
+
const fromAave = await fetchAaveV4NativeWrappedToken(chainId);
|
|
1815
|
+
if (fromAave) return fromAave;
|
|
1816
|
+
} catch {
|
|
1817
|
+
}
|
|
1818
|
+
const fb = WRAPPED_NATIVE_FALLBACK[chainId];
|
|
1819
|
+
if (fb && isAddress(fb)) return getAddress(fb);
|
|
1820
|
+
return null;
|
|
1821
|
+
}
|
|
1822
|
+
async function eulerWrappedGasTokenAliasesLower(chainId) {
|
|
1823
|
+
const s = /* @__PURE__ */ new Set();
|
|
1824
|
+
const fb = WRAPPED_NATIVE_FALLBACK[chainId];
|
|
1825
|
+
if (fb && isAddress(fb)) {
|
|
1826
|
+
try {
|
|
1827
|
+
s.add(getAddress(fb).toLowerCase());
|
|
1828
|
+
} catch {
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
try {
|
|
1832
|
+
const aave = await fetchAaveV4NativeWrappedToken(chainId);
|
|
1833
|
+
if (aave && isAddress(aave)) s.add(getAddress(aave).toLowerCase());
|
|
1834
|
+
} catch {
|
|
1835
|
+
}
|
|
1836
|
+
return s;
|
|
1837
|
+
}
|
|
1838
|
+
function eulerV2KeyForNodeAssetRow(args) {
|
|
1839
|
+
const raw = (args.contractAddress ?? "").trim();
|
|
1840
|
+
try {
|
|
1841
|
+
const a = getAddress(raw);
|
|
1842
|
+
if (a.toLowerCase() === "0x0000000000000000000000000000000000000000" && args.nativeWrapped) {
|
|
1843
|
+
return getAddress(args.nativeWrapped.trim()).toLowerCase();
|
|
1844
|
+
}
|
|
1845
|
+
return a.toLowerCase();
|
|
1846
|
+
} catch {
|
|
1847
|
+
return null;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
async function eulerSubgraphGql(endpoint, query, variables, chainId) {
|
|
1851
|
+
const body = { query, variables: variables ?? {} };
|
|
1852
|
+
const proxy = getEulerGraphqlProxyUrl();
|
|
1853
|
+
const j = await postJsonViaOptionalProxy({
|
|
1854
|
+
directUrl: endpoint,
|
|
1855
|
+
body,
|
|
1856
|
+
proxyUrl: proxy,
|
|
1857
|
+
proxyEnvelope: chainId != null ? { chainId, query, variables: variables ?? {} } : body
|
|
1858
|
+
});
|
|
1859
|
+
if (j.errors?.length) {
|
|
1860
|
+
throw new Error(j.errors.map((e) => e.message ?? "Unknown").join("; "));
|
|
1861
|
+
}
|
|
1862
|
+
if (j.data == null) throw new Error("Euler subgraph: empty response");
|
|
1863
|
+
return j.data;
|
|
1864
|
+
}
|
|
1865
|
+
async function eulerV2QueryGraphQl(chainId, query, variables) {
|
|
1866
|
+
const endpoint = eulerV2GoldskyUrlForChain(chainId);
|
|
1867
|
+
if (!endpoint) {
|
|
1868
|
+
throw new Error(`Euler v2 subgraph is not configured for chain ${chainId}`);
|
|
1869
|
+
}
|
|
1870
|
+
return eulerSubgraphGql(endpoint, query, variables, chainId);
|
|
1871
|
+
}
|
|
1872
|
+
var EULER_TRACKING_DEPOSITS_GQL = `
|
|
1873
|
+
query EulerTrackingDeposits($id: Bytes!) {
|
|
1874
|
+
trackingActiveAccount(id: $id) {
|
|
1875
|
+
deposits
|
|
1876
|
+
}
|
|
1877
|
+
}`;
|
|
1878
|
+
async function fetchEulerV2TrackingDepositEntries(args) {
|
|
1879
|
+
if (!eulerV2GoldskyUrlForChain(args.chainId)) return [];
|
|
1880
|
+
const id = args.mainAddress.toLowerCase();
|
|
1881
|
+
const data = await eulerV2QueryGraphQl(
|
|
1882
|
+
args.chainId,
|
|
1883
|
+
EULER_TRACKING_DEPOSITS_GQL,
|
|
1884
|
+
{ id }
|
|
1885
|
+
);
|
|
1886
|
+
const raw = data.trackingActiveAccount?.deposits ?? [];
|
|
1887
|
+
return raw.filter((x) => typeof x === "string" && x.trim().length > 0);
|
|
1888
|
+
}
|
|
1889
|
+
function normAssetAddr(raw) {
|
|
1890
|
+
const s = (raw ?? "").trim();
|
|
1891
|
+
if (!s || !isAddress(s)) return null;
|
|
1892
|
+
return getAddress(s).toLowerCase();
|
|
1893
|
+
}
|
|
1894
|
+
function vaultShowsBorrowTab(borrowCap, totalBorrows) {
|
|
1895
|
+
let borrows = 0n;
|
|
1896
|
+
try {
|
|
1897
|
+
borrows = BigInt((totalBorrows ?? "").trim() || "0");
|
|
1898
|
+
} catch {
|
|
1899
|
+
borrows = 0n;
|
|
1900
|
+
}
|
|
1901
|
+
if (borrows > 0n) return true;
|
|
1902
|
+
const w = eulerSubgraphVaultCapToUnderlyingWei(borrowCap);
|
|
1903
|
+
if (w >= EULER_EVAULT_CAP_UNLIMITED_WEI - 3n) return true;
|
|
1904
|
+
return w > 0n;
|
|
1905
|
+
}
|
|
1906
|
+
var VAULT_PAGE = `
|
|
1907
|
+
query V($first: Int!, $skip: Int!) {
|
|
1908
|
+
eulerVaults(first: $first, skip: $skip) {
|
|
1909
|
+
asset
|
|
1910
|
+
borrowCap
|
|
1911
|
+
state { totalBorrows }
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
`;
|
|
1915
|
+
var EARN_PAGE = `
|
|
1916
|
+
query E($first: Int!, $skip: Int!) {
|
|
1917
|
+
eulerEarnVaults(first: $first, skip: $skip) {
|
|
1918
|
+
asset
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
`;
|
|
1922
|
+
async function paginateEulerVaultRows(endpoint) {
|
|
1923
|
+
const out = [];
|
|
1924
|
+
let skip = 0;
|
|
1925
|
+
const first = 1e3;
|
|
1926
|
+
while (true) {
|
|
1927
|
+
const d = await eulerSubgraphGql(endpoint, VAULT_PAGE, { first, skip });
|
|
1928
|
+
const rows = d.eulerVaults ?? [];
|
|
1929
|
+
if (!rows.length) break;
|
|
1930
|
+
for (const r of rows) {
|
|
1931
|
+
const tb = (r.state?.totalBorrows ?? "0").toString();
|
|
1932
|
+
out.push({ asset: r.asset ?? null, borrowCap: r.borrowCap, totalBorrows: tb });
|
|
1933
|
+
}
|
|
1934
|
+
if (rows.length < first) break;
|
|
1935
|
+
skip += first;
|
|
1936
|
+
}
|
|
1937
|
+
return out;
|
|
1938
|
+
}
|
|
1939
|
+
async function paginateEulerEarnAssets(endpoint) {
|
|
1940
|
+
const assets = [];
|
|
1941
|
+
let skip = 0;
|
|
1942
|
+
const first = 1e3;
|
|
1943
|
+
while (true) {
|
|
1944
|
+
const d = await eulerSubgraphGql(endpoint, EARN_PAGE, {
|
|
1945
|
+
first,
|
|
1946
|
+
skip
|
|
1947
|
+
});
|
|
1948
|
+
const rows = d.eulerEarnVaults ?? [];
|
|
1949
|
+
if (!rows.length) break;
|
|
1950
|
+
for (const r of rows) {
|
|
1951
|
+
const a = normAssetAddr(r.asset ?? void 0);
|
|
1952
|
+
if (a) assets.push(a);
|
|
1953
|
+
}
|
|
1954
|
+
if (rows.length < first) break;
|
|
1955
|
+
skip += first;
|
|
1956
|
+
}
|
|
1957
|
+
return assets;
|
|
1958
|
+
}
|
|
1959
|
+
var eulerV2ChainAssetCache = /* @__PURE__ */ new Map();
|
|
1960
|
+
async function fetchEulerV2ChainAssetCache(chainId) {
|
|
1961
|
+
const endpoint = eulerV2GoldskyUrlForChain(chainId);
|
|
1962
|
+
if (!endpoint) {
|
|
1963
|
+
return { nativeWrapped: null, modesByUnderlying: /* @__PURE__ */ new Map() };
|
|
1964
|
+
}
|
|
1965
|
+
const [nativeWrapped, vaultRows, earnAssets] = await Promise.all([
|
|
1966
|
+
resolveEulerWrappedNativeToken(chainId),
|
|
1967
|
+
paginateEulerVaultRows(endpoint),
|
|
1968
|
+
paginateEulerEarnAssets(endpoint)
|
|
1969
|
+
]);
|
|
1970
|
+
const modes = /* @__PURE__ */ new Map();
|
|
1971
|
+
const bump = (addr, patch) => {
|
|
1972
|
+
const cur = modes.get(addr) ?? { lend: false, borrow: false, earn: false };
|
|
1973
|
+
modes.set(addr, {
|
|
1974
|
+
lend: cur.lend || !!patch.lend,
|
|
1975
|
+
borrow: cur.borrow || !!patch.borrow,
|
|
1976
|
+
earn: cur.earn || !!patch.earn
|
|
1977
|
+
});
|
|
1978
|
+
};
|
|
1979
|
+
for (const e of earnAssets) bump(e, { earn: true });
|
|
1980
|
+
for (const row of vaultRows) {
|
|
1981
|
+
const a = normAssetAddr(row.asset);
|
|
1982
|
+
if (!a) continue;
|
|
1983
|
+
bump(a, {
|
|
1984
|
+
lend: true,
|
|
1985
|
+
borrow: vaultShowsBorrowTab(row.borrowCap, row.totalBorrows)
|
|
1986
|
+
});
|
|
1987
|
+
}
|
|
1988
|
+
return { nativeWrapped, modesByUnderlying: modes };
|
|
1989
|
+
}
|
|
1990
|
+
function ensureEulerV2ChainAssetCache(chainId) {
|
|
1991
|
+
const hit = eulerV2ChainAssetCache.get(chainId);
|
|
1992
|
+
if (hit) return hit;
|
|
1993
|
+
const p = fetchEulerV2ChainAssetCache(chainId);
|
|
1994
|
+
eulerV2ChainAssetCache.set(chainId, p);
|
|
1995
|
+
return p;
|
|
1996
|
+
}
|
|
1997
|
+
var LABELS_PRODUCTS_URL = (chainId) => `https://raw.githubusercontent.com/euler-xyz/euler-labels/master/${chainId}/products.json`;
|
|
1998
|
+
function normAddrKey(raw) {
|
|
1999
|
+
const s = (raw ?? "").trim();
|
|
2000
|
+
if (!s) return null;
|
|
2001
|
+
try {
|
|
2002
|
+
return getAddress(s.startsWith("0x") ? s : `0x${s}`).toLowerCase();
|
|
2003
|
+
} catch {
|
|
2004
|
+
return null;
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
function eulerLabelsAppendUnderlyingIfDistinct(base, underlyingSymbol) {
|
|
2008
|
+
const b = (base ?? "").trim();
|
|
2009
|
+
const sym = (underlyingSymbol ?? "").trim();
|
|
2010
|
+
if (!b) return "\u2014";
|
|
2011
|
+
if (!sym) return b;
|
|
2012
|
+
if (b.toLowerCase().includes(sym.toLowerCase())) return b;
|
|
2013
|
+
return `${b} ${sym}`;
|
|
2014
|
+
}
|
|
2015
|
+
var labelMapCache = /* @__PURE__ */ new Map();
|
|
2016
|
+
function fetchEulerLabelsVaultNameMap(chainId) {
|
|
2017
|
+
let hit = labelMapCache.get(chainId);
|
|
2018
|
+
if (!hit) {
|
|
2019
|
+
hit = (async () => {
|
|
2020
|
+
const m = /* @__PURE__ */ new Map();
|
|
2021
|
+
try {
|
|
2022
|
+
const res = await fetch(LABELS_PRODUCTS_URL(chainId), { cache: "force-cache" });
|
|
2023
|
+
if (!res.ok) return m;
|
|
2024
|
+
const j = await res.json();
|
|
2025
|
+
if (!j || typeof j !== "object") return m;
|
|
2026
|
+
for (const prod of Object.values(j)) {
|
|
2027
|
+
const productName = (prod?.name ?? "").trim();
|
|
2028
|
+
const vaults = prod?.vaults ?? [];
|
|
2029
|
+
const overrides = prod?.vaultOverrides ?? {};
|
|
2030
|
+
const overrideNameByVault = /* @__PURE__ */ new Map();
|
|
2031
|
+
for (const [addr, ov] of Object.entries(overrides)) {
|
|
2032
|
+
const k = normAddrKey(addr);
|
|
2033
|
+
const n = (ov?.name ?? "").trim();
|
|
2034
|
+
if (k && n) overrideNameByVault.set(k, n);
|
|
2035
|
+
}
|
|
2036
|
+
for (const vAddr of vaults) {
|
|
2037
|
+
const k = normAddrKey(vAddr);
|
|
2038
|
+
if (!k) continue;
|
|
2039
|
+
const overrideName = overrideNameByVault.get(k);
|
|
2040
|
+
const base = overrideName || productName;
|
|
2041
|
+
if (!base) continue;
|
|
2042
|
+
m.set(k, base);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
} catch {
|
|
2046
|
+
}
|
|
2047
|
+
return m;
|
|
2048
|
+
})();
|
|
2049
|
+
labelMapCache.set(chainId, hit);
|
|
2050
|
+
}
|
|
2051
|
+
return hit;
|
|
2052
|
+
}
|
|
2053
|
+
function eulerLabelsLookupLabelForVault(labelMap, evaultAddress) {
|
|
2054
|
+
const k = normAddrKey(evaultAddress);
|
|
2055
|
+
if (!k) return void 0;
|
|
2056
|
+
const v = labelMap.get(k);
|
|
2057
|
+
return typeof v === "string" && v.trim() ? v.trim() : void 0;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
// src/protocols/evm/euler-v2/eulerV2LendMarkets.ts
|
|
2061
|
+
var erc20StringMetaAbi = parseAbi([
|
|
2062
|
+
"function name() view returns (string)",
|
|
2063
|
+
"function symbol() view returns (string)"
|
|
2064
|
+
]);
|
|
2065
|
+
var LEND_VAULT_PAGE = `
|
|
2066
|
+
query EulerLendVaults($first: Int!, $skip: Int!, $asset: Bytes!) {
|
|
2067
|
+
eulerVaults(
|
|
2068
|
+
first: $first
|
|
2069
|
+
skip: $skip
|
|
2070
|
+
where: { asset: $asset }
|
|
2071
|
+
orderBy: state__supplyApy
|
|
2072
|
+
orderDirection: desc
|
|
2073
|
+
) {
|
|
2074
|
+
id
|
|
2075
|
+
evc
|
|
2076
|
+
evault
|
|
2077
|
+
name
|
|
2078
|
+
symbol
|
|
2079
|
+
asset
|
|
2080
|
+
decimals
|
|
2081
|
+
supplyCap
|
|
2082
|
+
borrowCap
|
|
2083
|
+
interestFee
|
|
2084
|
+
perspectives
|
|
2085
|
+
collaterals
|
|
2086
|
+
oracle
|
|
2087
|
+
unitOfAccount
|
|
2088
|
+
governonAdmin
|
|
2089
|
+
state {
|
|
2090
|
+
cash
|
|
2091
|
+
totalBorrows
|
|
2092
|
+
totalShares
|
|
2093
|
+
supplyApy
|
|
2094
|
+
borrowApy
|
|
2095
|
+
timestamp
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
`;
|
|
2100
|
+
var COLLATERAL_META = `
|
|
2101
|
+
query EulerCollateralVaults($first: Int!, $ids: [Bytes!]!) {
|
|
2102
|
+
eulerVaults(first: $first, where: { id_in: $ids }) {
|
|
2103
|
+
id
|
|
2104
|
+
evault
|
|
2105
|
+
name
|
|
2106
|
+
symbol
|
|
2107
|
+
asset
|
|
2108
|
+
decimals
|
|
2109
|
+
state {
|
|
2110
|
+
supplyApy
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
`;
|
|
2115
|
+
function normId(raw) {
|
|
2116
|
+
const s = (raw ?? "").trim().toLowerCase();
|
|
2117
|
+
return s.length ? s : null;
|
|
2118
|
+
}
|
|
2119
|
+
function normAssetLower(raw) {
|
|
2120
|
+
const s = (raw ?? "").trim();
|
|
2121
|
+
if (!s || !isAddress(s)) return null;
|
|
2122
|
+
return getAddress(s).toLowerCase();
|
|
2123
|
+
}
|
|
2124
|
+
function checksumHex(raw) {
|
|
2125
|
+
const s = (raw ?? "").trim();
|
|
2126
|
+
if (!s || !isAddress(s)) return null;
|
|
2127
|
+
try {
|
|
2128
|
+
return getAddress(s);
|
|
2129
|
+
} catch {
|
|
2130
|
+
return null;
|
|
2131
|
+
}
|
|
2132
|
+
}
|
|
2133
|
+
function eulerMetaPublicClient(chainId, rpcUrl) {
|
|
2134
|
+
const chain = defineChain({
|
|
2135
|
+
id: chainId,
|
|
2136
|
+
name: "EulerCollateralMeta",
|
|
2137
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
2138
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
2139
|
+
});
|
|
2140
|
+
return createPublicClient({ chain, transport: http(rpcUrl) });
|
|
2141
|
+
}
|
|
2142
|
+
async function readErc20StringMeta(client, addrLower) {
|
|
2143
|
+
try {
|
|
2144
|
+
const addr = getAddress(addrLower);
|
|
2145
|
+
const [nameResult, symbolResult] = await Promise.all([
|
|
2146
|
+
client.readContract({ address: addr, abi: erc20StringMetaAbi, functionName: "name" }),
|
|
2147
|
+
client.readContract({ address: addr, abi: erc20StringMetaAbi, functionName: "symbol" })
|
|
2148
|
+
]);
|
|
2149
|
+
return {
|
|
2150
|
+
name: typeof nameResult === "string" ? nameResult.trim() : String(nameResult ?? "").trim(),
|
|
2151
|
+
symbol: typeof symbolResult === "string" ? symbolResult.trim() : String(symbolResult ?? "").trim()
|
|
2152
|
+
};
|
|
2153
|
+
} catch {
|
|
2154
|
+
return null;
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
async function resolveUnderlyingTokenLabels(args) {
|
|
2158
|
+
const out = /* @__PURE__ */ new Map();
|
|
2159
|
+
const uniq = [...new Set(args.assetAddresses.map((a) => normAssetLower(a)).filter(Boolean))];
|
|
2160
|
+
const missingFromNode = [];
|
|
2161
|
+
const node = args.nodeErc20ByAddress;
|
|
2162
|
+
for (const low of uniq) {
|
|
2163
|
+
const hit = node?.get(low);
|
|
2164
|
+
if (hit && ((hit.symbol ?? "").trim() || (hit.name ?? "").trim())) {
|
|
2165
|
+
out.set(low, { name: (hit.name ?? "").trim(), symbol: (hit.symbol ?? "").trim() });
|
|
2166
|
+
} else {
|
|
2167
|
+
missingFromNode.push(low);
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
const rpc = (args.rpcUrl ?? "").trim();
|
|
2171
|
+
if (!missingFromNode.length || !rpc) return out;
|
|
2172
|
+
const client = eulerMetaPublicClient(args.chainId, rpc);
|
|
2173
|
+
const batchSize = 10;
|
|
2174
|
+
for (let i = 0; i < missingFromNode.length; i += batchSize) {
|
|
2175
|
+
const chunk = missingFromNode.slice(i, i + batchSize);
|
|
2176
|
+
const settled = await Promise.all(chunk.map((low) => readErc20StringMeta(client, low)));
|
|
2177
|
+
chunk.forEach((low, j) => {
|
|
2178
|
+
const m = settled[j];
|
|
2179
|
+
if (m && (m.symbol || m.name)) out.set(low, m);
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2182
|
+
return out;
|
|
2183
|
+
}
|
|
2184
|
+
function formatEulerRayApyPercent(apyRay) {
|
|
2185
|
+
if (apyRay === 0n) return "0.00%";
|
|
2186
|
+
const r = Number(formatUnits(apyRay, 27));
|
|
2187
|
+
if (!Number.isFinite(r)) return "\u2014";
|
|
2188
|
+
const pct = r * 100;
|
|
2189
|
+
if (pct >= 100) return `${pct.toFixed(1)}%`;
|
|
2190
|
+
if (pct >= 10) return `${pct.toFixed(2)}%`;
|
|
2191
|
+
return `${pct.toFixed(2)}%`;
|
|
2192
|
+
}
|
|
2193
|
+
var formatEulerRaySupplyApyPercent = formatEulerRayApyPercent;
|
|
2194
|
+
function formatUnderlyingAmount(raw, decimals) {
|
|
2195
|
+
try {
|
|
2196
|
+
const v = BigInt((raw ?? "").trim() || "0");
|
|
2197
|
+
const s = formatUnits(v, decimals);
|
|
2198
|
+
const n = Number(s);
|
|
2199
|
+
if (!Number.isFinite(n)) return s;
|
|
2200
|
+
if (n === 0) return "0";
|
|
2201
|
+
const abs = Math.abs(n);
|
|
2202
|
+
if (abs >= 1e9) return n.toExponential(2);
|
|
2203
|
+
if (abs >= 1e6) return n.toLocaleString(void 0, { maximumFractionDigits: 0 });
|
|
2204
|
+
if (abs >= 1) return n.toLocaleString(void 0, { maximumFractionDigits: 2 });
|
|
2205
|
+
return n.toLocaleString(void 0, { maximumFractionDigits: 6 });
|
|
2206
|
+
} catch {
|
|
2207
|
+
return "\u2014";
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
function formatEulerVaultCapDisplay(raw, decimals) {
|
|
2211
|
+
try {
|
|
2212
|
+
const wei = eulerSubgraphVaultCapToUnderlyingWei(raw);
|
|
2213
|
+
if (wei >= EULER_EVAULT_CAP_UNLIMITED_WEI - 3n) return "Unlimited";
|
|
2214
|
+
if (wei === 0n) return "0";
|
|
2215
|
+
return formatUnderlyingAmount(wei.toString(), decimals);
|
|
2216
|
+
} catch {
|
|
2217
|
+
return "\u2014";
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
function formatEulerInterestFee(raw) {
|
|
2221
|
+
try {
|
|
2222
|
+
const fee = BigInt((raw ?? "").trim() || "0");
|
|
2223
|
+
if (fee === 0n) return "0%";
|
|
2224
|
+
const pct = Number(fee) / 100;
|
|
2225
|
+
return `${pct.toFixed(2)}%`;
|
|
2226
|
+
} catch {
|
|
2227
|
+
return "\u2014";
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
function formatEulerIndexedTimestamp(raw) {
|
|
2231
|
+
try {
|
|
2232
|
+
const sec = BigInt((raw ?? "").trim() || "0");
|
|
2233
|
+
const n = Number(sec);
|
|
2234
|
+
if (!Number.isFinite(n) || n <= 0) return "\u2014";
|
|
2235
|
+
return new Date(n * 1e3).toLocaleString(void 0, {
|
|
2236
|
+
dateStyle: "medium",
|
|
2237
|
+
timeStyle: "short"
|
|
2238
|
+
});
|
|
2239
|
+
} catch {
|
|
2240
|
+
return "\u2014";
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
function utilizationPercentLabel(cash, borrows) {
|
|
2244
|
+
const denom = cash + borrows;
|
|
2245
|
+
if (denom === 0n) return "0.00%";
|
|
2246
|
+
const scaled = borrows * 1000000n / denom;
|
|
2247
|
+
const pct = Number(scaled) / 1e4;
|
|
2248
|
+
return `${pct.toFixed(2)}%`;
|
|
2249
|
+
}
|
|
2250
|
+
function collateralLabelFromVault(name, symbol, id) {
|
|
2251
|
+
const n = (name ?? "").trim();
|
|
2252
|
+
const sym = (symbol ?? "").trim();
|
|
2253
|
+
if (n && sym && n.toLowerCase() !== sym.toLowerCase()) return `${n} (${sym})`;
|
|
2254
|
+
if (n) return n;
|
|
2255
|
+
if (sym) return sym;
|
|
2256
|
+
return id.slice(0, 10);
|
|
2257
|
+
}
|
|
2258
|
+
function marketLabelFromSubgraphRow(r, evaultChecksum) {
|
|
2259
|
+
const n = (r.name ?? "").trim();
|
|
2260
|
+
if (n) return n;
|
|
2261
|
+
const sym = (r.symbol ?? "").trim();
|
|
2262
|
+
if (sym) return sym;
|
|
2263
|
+
const addr = (evaultChecksum ?? "").trim();
|
|
2264
|
+
if (addr.startsWith("0x") && addr.length >= 14) return `${addr.slice(0, 8)}\u2026${addr.slice(-6)}`;
|
|
2265
|
+
return addr || "\u2014";
|
|
2266
|
+
}
|
|
2267
|
+
function normalizePerspectives(raw) {
|
|
2268
|
+
const out = [];
|
|
2269
|
+
for (const p of raw ?? []) {
|
|
2270
|
+
const s = (p ?? "").trim();
|
|
2271
|
+
if (s) out.push(s);
|
|
2272
|
+
}
|
|
2273
|
+
return out;
|
|
2274
|
+
}
|
|
2275
|
+
function vaultSupplyBorrowApyRays(r) {
|
|
2276
|
+
let supplyApyRay = 0n;
|
|
2277
|
+
let borrowApyRay = 0n;
|
|
2278
|
+
try {
|
|
2279
|
+
supplyApyRay = BigInt((r.state?.supplyApy ?? "0").toString().trim() || "0");
|
|
2280
|
+
} catch {
|
|
2281
|
+
supplyApyRay = 0n;
|
|
2282
|
+
}
|
|
2283
|
+
try {
|
|
2284
|
+
borrowApyRay = BigInt((r.state?.borrowApy ?? "0").toString().trim() || "0");
|
|
2285
|
+
} catch {
|
|
2286
|
+
borrowApyRay = 0n;
|
|
2287
|
+
}
|
|
2288
|
+
return { supplyApyRay, borrowApyRay };
|
|
2289
|
+
}
|
|
2290
|
+
function vaultCashAndBorrows(r) {
|
|
2291
|
+
let cash = 0n;
|
|
2292
|
+
let borrows = 0n;
|
|
2293
|
+
try {
|
|
2294
|
+
cash = BigInt((r.state?.cash ?? "0").toString().trim() || "0");
|
|
2295
|
+
} catch {
|
|
2296
|
+
cash = 0n;
|
|
2297
|
+
}
|
|
2298
|
+
try {
|
|
2299
|
+
borrows = BigInt((r.state?.totalBorrows ?? "0").toString().trim() || "0");
|
|
2300
|
+
} catch {
|
|
2301
|
+
borrows = 0n;
|
|
2302
|
+
}
|
|
2303
|
+
return { cash, borrows };
|
|
2304
|
+
}
|
|
2305
|
+
async function paginateLendVaultRows(chainId, assetLower) {
|
|
2306
|
+
const out = [];
|
|
2307
|
+
let skip = 0;
|
|
2308
|
+
const first = 500;
|
|
2309
|
+
while (true) {
|
|
2310
|
+
const d = await eulerV2QueryGraphQl(chainId, LEND_VAULT_PAGE, {
|
|
2311
|
+
first,
|
|
2312
|
+
skip,
|
|
2313
|
+
asset: assetLower
|
|
2314
|
+
});
|
|
2315
|
+
const rows = d.eulerVaults ?? [];
|
|
2316
|
+
if (!rows.length) break;
|
|
2317
|
+
out.push(...rows);
|
|
2318
|
+
if (rows.length < first) break;
|
|
2319
|
+
skip += first;
|
|
2320
|
+
}
|
|
2321
|
+
return out;
|
|
2322
|
+
}
|
|
2323
|
+
async function fetchCollateralVaultMeta(chainId, collateralIds) {
|
|
2324
|
+
const map = /* @__PURE__ */ new Map();
|
|
2325
|
+
const uniq = [...new Set(collateralIds.map((x) => x.toLowerCase()))].filter(Boolean);
|
|
2326
|
+
const chunkSize = 400;
|
|
2327
|
+
for (let i = 0; i < uniq.length; i += chunkSize) {
|
|
2328
|
+
const chunk = uniq.slice(i, i + chunkSize);
|
|
2329
|
+
const d = await eulerV2QueryGraphQl(chainId, COLLATERAL_META, { first: chunk.length, ids: chunk });
|
|
2330
|
+
for (const r of d.eulerVaults ?? []) {
|
|
2331
|
+
const id = normId(r.id ?? void 0);
|
|
2332
|
+
if (!id) continue;
|
|
2333
|
+
let dec = 18;
|
|
2334
|
+
try {
|
|
2335
|
+
dec = Number.parseInt((r.decimals ?? "18").trim(), 10);
|
|
2336
|
+
if (!Number.isFinite(dec) || dec < 0 || dec > 36) dec = 18;
|
|
2337
|
+
} catch {
|
|
2338
|
+
dec = 18;
|
|
2339
|
+
}
|
|
2340
|
+
let supplyApyRay = 0n;
|
|
2341
|
+
try {
|
|
2342
|
+
supplyApyRay = BigInt((r.state?.supplyApy ?? "0").toString().trim() || "0");
|
|
2343
|
+
} catch {
|
|
2344
|
+
supplyApyRay = 0n;
|
|
2345
|
+
}
|
|
2346
|
+
map.set(id, {
|
|
2347
|
+
name: (r.name ?? "").trim(),
|
|
2348
|
+
symbol: (r.symbol ?? "").trim(),
|
|
2349
|
+
assetLower: normAssetLower(r.asset ?? void 0),
|
|
2350
|
+
evaultChecksum: checksumHex(r.evault ?? void 0) ?? checksumHex(r.id ?? void 0),
|
|
2351
|
+
decimals: dec,
|
|
2352
|
+
supplyApyRay
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
return map;
|
|
2357
|
+
}
|
|
2358
|
+
function flattenEulerV2BorrowCollateralRows(markets) {
|
|
2359
|
+
const out = [];
|
|
2360
|
+
for (const m of markets) {
|
|
2361
|
+
if (m.borrowApyRay === 0n) continue;
|
|
2362
|
+
const borrowNum = Number.parseFloat(m.borrowApyPercentLabel.replace(/%/g, "").trim()) || 0;
|
|
2363
|
+
for (const c of m.collateralTokens) {
|
|
2364
|
+
if (!c.collateralEvaultAddress) continue;
|
|
2365
|
+
const supplyNum = Number.parseFloat(c.collateralSupplyApyPercentLabel.replace(/%/g, "").trim()) || 0;
|
|
2366
|
+
const net = supplyNum - borrowNum;
|
|
2367
|
+
const netLabel = `${net.toFixed(2)}%`;
|
|
2368
|
+
out.push({
|
|
2369
|
+
pairKey: `${m.vaultId}:${c.vaultId}`,
|
|
2370
|
+
borrowVaultId: m.vaultId,
|
|
2371
|
+
borrowEvaultAddress: m.evaultAddress,
|
|
2372
|
+
borrowMarketName: m.marketName,
|
|
2373
|
+
borrowDecimals: m.decimals,
|
|
2374
|
+
borrowApyPercentLabel: m.borrowApyPercentLabel,
|
|
2375
|
+
borrowCash: m.cash,
|
|
2376
|
+
borrowTotalBorrows: m.totalBorrows,
|
|
2377
|
+
netApyPercentLabel: netLabel,
|
|
2378
|
+
utilizationPercentLabel: m.utilizationPercentLabel,
|
|
2379
|
+
availableLiquidityFormatted: m.availableLiquidityFormatted,
|
|
2380
|
+
evcAddress: m.evcAddress,
|
|
2381
|
+
oracleAddress: m.oracleAddress,
|
|
2382
|
+
unitOfAccountAddress: m.unitOfAccountAddress,
|
|
2383
|
+
borrowAssetAddressLower: m.borrowAssetAddressLower,
|
|
2384
|
+
governonAdminChecksum: m.governonAdminChecksum,
|
|
2385
|
+
collateralVaultId: c.vaultId,
|
|
2386
|
+
collateralEvaultAddress: c.collateralEvaultAddress,
|
|
2387
|
+
collateralSymbol: c.underlyingSymbol,
|
|
2388
|
+
collateralName: c.underlyingName,
|
|
2389
|
+
collateralVaultLabel: c.vaultMarketLabel,
|
|
2390
|
+
collateralDecimals: c.collateralDecimals,
|
|
2391
|
+
collateralAssetAddressLower: c.collateralAssetAddressLower,
|
|
2392
|
+
collateralSupplyApyPercentLabel: c.collateralSupplyApyPercentLabel,
|
|
2393
|
+
borrowIndexerLendMetrics: m.indexerLendMetrics
|
|
2394
|
+
});
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
return out;
|
|
2398
|
+
}
|
|
2399
|
+
async function fetchEulerV2IsolatedLendMarketsForRowAsset(args) {
|
|
2400
|
+
const cache = await ensureEulerV2ChainAssetCache(args.chainId);
|
|
2401
|
+
const underlying = eulerV2KeyForNodeAssetRow({
|
|
2402
|
+
contractAddress: args.contractAddress,
|
|
2403
|
+
nativeWrapped: cache.nativeWrapped
|
|
2404
|
+
});
|
|
2405
|
+
if (!underlying) return [];
|
|
2406
|
+
const [gqlRows, labelMap] = await Promise.all([
|
|
2407
|
+
paginateLendVaultRows(args.chainId, underlying),
|
|
2408
|
+
fetchEulerLabelsVaultNameMap(args.chainId)
|
|
2409
|
+
]);
|
|
2410
|
+
const eligibleRows = gqlRows.filter((r) => {
|
|
2411
|
+
const { supplyApyRay, borrowApyRay } = vaultSupplyBorrowApyRays(r);
|
|
2412
|
+
if (supplyApyRay === 0n && borrowApyRay === 0n) return false;
|
|
2413
|
+
const { cash, borrows } = vaultCashAndBorrows(r);
|
|
2414
|
+
return cash + borrows !== 0n;
|
|
2415
|
+
});
|
|
2416
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV === "development") {
|
|
2417
|
+
let matched = 0;
|
|
2418
|
+
for (const r of eligibleRows) {
|
|
2419
|
+
const evRaw = checksumHex(r.evault ?? void 0) ?? checksumHex(r.id ?? void 0);
|
|
2420
|
+
if (!evRaw) continue;
|
|
2421
|
+
if (eulerLabelsLookupLabelForVault(labelMap, evRaw)) matched += 1;
|
|
2422
|
+
}
|
|
2423
|
+
console.debug("[Euler labels]", {
|
|
2424
|
+
chainId: args.chainId,
|
|
2425
|
+
matchedEligibleVaults: matched,
|
|
2426
|
+
eligibleVaults: eligibleRows.length,
|
|
2427
|
+
labelMapEntries: labelMap.size
|
|
2428
|
+
});
|
|
2429
|
+
}
|
|
2430
|
+
const collateralIds = [];
|
|
2431
|
+
for (const r of eligibleRows) {
|
|
2432
|
+
for (const c of r.collaterals ?? []) {
|
|
2433
|
+
const id = normId(c ?? void 0);
|
|
2434
|
+
if (id) collateralIds.push(id);
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
const collateralMeta = await fetchCollateralVaultMeta(args.chainId, collateralIds);
|
|
2438
|
+
const underlyingAssetAddrs = [];
|
|
2439
|
+
for (const m of collateralMeta.values()) {
|
|
2440
|
+
if (m.assetLower) underlyingAssetAddrs.push(m.assetLower);
|
|
2441
|
+
}
|
|
2442
|
+
const underlyingLabels = await resolveUnderlyingTokenLabels({
|
|
2443
|
+
chainId: args.chainId,
|
|
2444
|
+
rpcUrl: args.rpcUrl,
|
|
2445
|
+
nodeErc20ByAddress: args.nodeErc20ByAddress,
|
|
2446
|
+
assetAddresses: underlyingAssetAddrs
|
|
2447
|
+
});
|
|
2448
|
+
const rows = [];
|
|
2449
|
+
for (const r of eligibleRows) {
|
|
2450
|
+
const vaultId = normId(r.id ?? void 0);
|
|
2451
|
+
if (!vaultId) continue;
|
|
2452
|
+
const evaultAddress = checksumHex(r.evault ?? void 0) ?? checksumHex(r.id ?? void 0) ?? vaultId;
|
|
2453
|
+
const subgraphTitle = marketLabelFromSubgraphRow(r, evaultAddress);
|
|
2454
|
+
const labelBase = eulerLabelsLookupLabelForVault(labelMap, evaultAddress);
|
|
2455
|
+
const assetSym = (args.suppliedAssetSymbol ?? "").trim();
|
|
2456
|
+
const marketName = labelBase ? eulerLabelsAppendUnderlyingIfDistinct(labelBase, assetSym) : subgraphTitle;
|
|
2457
|
+
let dec = 18;
|
|
2458
|
+
try {
|
|
2459
|
+
dec = Number.parseInt((r.decimals ?? "18").trim(), 10);
|
|
2460
|
+
if (!Number.isFinite(dec) || dec < 0 || dec > 36) dec = 18;
|
|
2461
|
+
} catch {
|
|
2462
|
+
dec = 18;
|
|
2463
|
+
}
|
|
2464
|
+
const { cash, borrows } = vaultCashAndBorrows(r);
|
|
2465
|
+
const { supplyApyRay, borrowApyRay } = vaultSupplyBorrowApyRays(r);
|
|
2466
|
+
const total = cash + borrows;
|
|
2467
|
+
const cIds = [...new Set((r.collaterals ?? []).map((x) => normId(x ?? void 0)).filter(Boolean))];
|
|
2468
|
+
const collateralTokens = cIds.map((cid) => {
|
|
2469
|
+
const vm = collateralMeta.get(cid);
|
|
2470
|
+
const vaultMarketLabel = vm ? collateralLabelFromVault(vm.name, vm.symbol, cid) : cid.slice(0, 10);
|
|
2471
|
+
const assetLow = vm?.assetLower ?? null;
|
|
2472
|
+
const und = assetLow ? underlyingLabels.get(assetLow) : void 0;
|
|
2473
|
+
const sym = (und?.symbol ?? "").trim();
|
|
2474
|
+
const nam = (und?.name ?? "").trim();
|
|
2475
|
+
let underlyingSymbol;
|
|
2476
|
+
let underlyingName;
|
|
2477
|
+
if (sym || nam) {
|
|
2478
|
+
underlyingSymbol = sym || nam;
|
|
2479
|
+
underlyingName = sym && nam && nam.toLowerCase() !== sym.toLowerCase() ? nam : null;
|
|
2480
|
+
} else {
|
|
2481
|
+
underlyingSymbol = vaultMarketLabel;
|
|
2482
|
+
underlyingName = null;
|
|
2483
|
+
}
|
|
2484
|
+
const collSupplyRay = vm?.supplyApyRay ?? 0n;
|
|
2485
|
+
return {
|
|
2486
|
+
vaultId: cid,
|
|
2487
|
+
collateralEvaultAddress: vm?.evaultChecksum ?? null,
|
|
2488
|
+
collateralDecimals: vm?.decimals ?? 18,
|
|
2489
|
+
collateralAssetAddressLower: assetLow,
|
|
2490
|
+
collateralSupplyApyPercentLabel: formatEulerRayApyPercent(collSupplyRay),
|
|
2491
|
+
underlyingSymbol,
|
|
2492
|
+
underlyingName,
|
|
2493
|
+
vaultMarketLabel
|
|
2494
|
+
};
|
|
2495
|
+
});
|
|
2496
|
+
const indexerLendMetrics = eulerVaultLendMetricsFromIndexerVaultState({
|
|
2497
|
+
supplyCapRaw: r.supplyCap,
|
|
2498
|
+
borrowCapRaw: r.borrowCap,
|
|
2499
|
+
cashWei: cash,
|
|
2500
|
+
totalBorrowsWei: borrows,
|
|
2501
|
+
totalAssetsWei: total
|
|
2502
|
+
});
|
|
2503
|
+
rows.push({
|
|
2504
|
+
vaultId,
|
|
2505
|
+
evaultAddress,
|
|
2506
|
+
marketName,
|
|
2507
|
+
decimals: dec,
|
|
2508
|
+
cash,
|
|
2509
|
+
totalBorrows: borrows,
|
|
2510
|
+
supplyApyPercentLabel: formatEulerRayApyPercent(supplyApyRay),
|
|
2511
|
+
borrowApyPercentLabel: formatEulerRayApyPercent(borrowApyRay),
|
|
2512
|
+
totalSupplyFormatted: formatUnderlyingAmount(total.toString(), dec),
|
|
2513
|
+
availableLiquidityFormatted: formatUnderlyingAmount(cash.toString(), dec),
|
|
2514
|
+
utilizationPercentLabel: utilizationPercentLabel(cash, borrows),
|
|
2515
|
+
supplyCapFormatted: formatEulerVaultCapDisplay(r.supplyCap, dec),
|
|
2516
|
+
borrowCapFormatted: formatEulerVaultCapDisplay(r.borrowCap, dec),
|
|
2517
|
+
interestFeeLabel: formatEulerInterestFee(r.interestFee),
|
|
2518
|
+
stateIndexedDisplay: formatEulerIndexedTimestamp(r.state?.timestamp),
|
|
2519
|
+
perspectives: normalizePerspectives(r.perspectives),
|
|
2520
|
+
evcAddress: checksumHex(r.evc ?? void 0),
|
|
2521
|
+
oracleAddress: checksumHex(r.oracle ?? void 0),
|
|
2522
|
+
unitOfAccountAddress: checksumHex(r.unitOfAccount ?? void 0),
|
|
2523
|
+
borrowAssetAddressLower: normAssetLower(r.asset ?? void 0),
|
|
2524
|
+
governonAdminChecksum: checksumHex(r.governonAdmin ?? void 0),
|
|
2525
|
+
borrowApyRay,
|
|
2526
|
+
indexerLendMetrics,
|
|
2527
|
+
collateralTokens
|
|
2528
|
+
});
|
|
2529
|
+
}
|
|
2530
|
+
return rows;
|
|
2531
|
+
}
|
|
2532
|
+
var UINT256_MAX2 = (1n << 256n) - 1n;
|
|
2533
|
+
var EARN_STRATEGY_ALLOC_CAP_SUBGRAPH_UNBOUNDED = 87112285931760246646623899502532662132735n;
|
|
2534
|
+
var EARN_VAULTS_QUERY = `
|
|
2535
|
+
query EulerEarnForAsset($asset: Bytes!, $ids: [Bytes!]!) {
|
|
2536
|
+
eulerEarnVaults(first: 500, where: { asset: $asset, id_in: $ids }) {
|
|
2537
|
+
id
|
|
2538
|
+
name
|
|
2539
|
+
curator
|
|
2540
|
+
performanceFee
|
|
2541
|
+
totalAssets
|
|
2542
|
+
totalAllocated
|
|
2543
|
+
asset
|
|
2544
|
+
strategies(first: 200) {
|
|
2545
|
+
strategy
|
|
2546
|
+
allocatedAssets
|
|
2547
|
+
availableAssets
|
|
2548
|
+
currentAllocationCap
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
`;
|
|
2553
|
+
var STRATEGY_VAULT_APY = `
|
|
2554
|
+
query EulerStrategyVaults($ids: [Bytes!]!) {
|
|
2555
|
+
eulerVaults(first: 500, where: { id_in: $ids }) {
|
|
2556
|
+
id
|
|
2557
|
+
asset
|
|
2558
|
+
symbol
|
|
2559
|
+
state {
|
|
2560
|
+
supplyApy
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
`;
|
|
2565
|
+
function normLowerId(raw) {
|
|
2566
|
+
const s = (raw ?? "").trim().toLowerCase();
|
|
2567
|
+
if (!s.startsWith("0x") || s.length < 4) return null;
|
|
2568
|
+
return s;
|
|
2569
|
+
}
|
|
2570
|
+
function big(raw) {
|
|
2571
|
+
try {
|
|
2572
|
+
return BigInt((raw ?? "0").toString().trim() || "0");
|
|
2573
|
+
} catch {
|
|
2574
|
+
return 0n;
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
async function fetchEulerLabelsEarnVaultAllowlist(chainId) {
|
|
2578
|
+
const url = `https://raw.githubusercontent.com/euler-xyz/euler-labels/master/${chainId}/earn-vaults.json`;
|
|
2579
|
+
const r = await fetch(url, { cache: "no-store" });
|
|
2580
|
+
if (!r.ok) return /* @__PURE__ */ new Set();
|
|
2581
|
+
let j;
|
|
2582
|
+
try {
|
|
2583
|
+
j = await r.json();
|
|
2584
|
+
} catch {
|
|
2585
|
+
return /* @__PURE__ */ new Set();
|
|
2586
|
+
}
|
|
2587
|
+
const out = /* @__PURE__ */ new Set();
|
|
2588
|
+
if (!Array.isArray(j)) return out;
|
|
2589
|
+
for (const entry of j) {
|
|
2590
|
+
if (typeof entry === "string") {
|
|
2591
|
+
const lo = normLowerId(entry);
|
|
2592
|
+
if (lo) out.add(lo);
|
|
2593
|
+
continue;
|
|
2594
|
+
}
|
|
2595
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
2596
|
+
const o = entry;
|
|
2597
|
+
if (o.deprecated === true) continue;
|
|
2598
|
+
const addr = typeof o.address === "string" ? o.address : typeof o.id === "string" ? o.id : null;
|
|
2599
|
+
const lo = normLowerId(addr);
|
|
2600
|
+
if (lo) out.add(lo);
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
return out;
|
|
2604
|
+
}
|
|
2605
|
+
async function fetchEulerLabelsEntityNameByAddress(chainId) {
|
|
2606
|
+
const url = `https://raw.githubusercontent.com/euler-xyz/euler-labels/master/${chainId}/entities.json`;
|
|
2607
|
+
const r = await fetch(url, { cache: "no-store" });
|
|
2608
|
+
const m = /* @__PURE__ */ new Map();
|
|
2609
|
+
if (!r.ok) return m;
|
|
2610
|
+
let j;
|
|
2611
|
+
try {
|
|
2612
|
+
j = await r.json();
|
|
2613
|
+
} catch {
|
|
2614
|
+
return m;
|
|
2615
|
+
}
|
|
2616
|
+
if (!j || typeof j !== "object") return m;
|
|
2617
|
+
for (const ent of Object.values(j)) {
|
|
2618
|
+
if (!ent || typeof ent !== "object") continue;
|
|
2619
|
+
const name = ent.name;
|
|
2620
|
+
const groupName = typeof name === "string" && name.trim() ? name.trim() : null;
|
|
2621
|
+
if (!groupName) continue;
|
|
2622
|
+
const addrs = ent.addresses;
|
|
2623
|
+
if (!addrs || typeof addrs !== "object") continue;
|
|
2624
|
+
for (const k of Object.keys(addrs)) {
|
|
2625
|
+
const lo = normLowerId(k);
|
|
2626
|
+
if (lo) m.set(lo, groupName);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
return m;
|
|
2630
|
+
}
|
|
2631
|
+
function formatPerformanceFeePercent(feeWad) {
|
|
2632
|
+
if (feeWad === 0n) return "0%";
|
|
2633
|
+
const x = Number(formatUnits(feeWad, 18));
|
|
2634
|
+
if (!Number.isFinite(x)) return "\u2014";
|
|
2635
|
+
const pct = x * 100;
|
|
2636
|
+
if (pct >= 10) return `${pct.toFixed(1)}%`;
|
|
2637
|
+
if (pct >= 1) return `${pct.toFixed(2)}%`;
|
|
2638
|
+
return `${pct.toFixed(2)}%`;
|
|
2639
|
+
}
|
|
2640
|
+
function isMaxUintCap(cap) {
|
|
2641
|
+
return cap >= UINT256_MAX2 - 3n;
|
|
2642
|
+
}
|
|
2643
|
+
function isUnboundedEarnStrategyAllocationCap(cap) {
|
|
2644
|
+
return isMaxUintCap(cap) || cap === EARN_STRATEGY_ALLOC_CAP_SUBGRAPH_UNBOUNDED;
|
|
2645
|
+
}
|
|
2646
|
+
async function fetchEulerV2EarnOfferingsForRowAsset(args) {
|
|
2647
|
+
const { chainId, underlyingDecimals } = args;
|
|
2648
|
+
const cache = await ensureEulerV2ChainAssetCache(chainId);
|
|
2649
|
+
const key = eulerV2KeyForNodeAssetRow({
|
|
2650
|
+
contractAddress: args.contractAddress,
|
|
2651
|
+
nativeWrapped: cache.nativeWrapped
|
|
2652
|
+
});
|
|
2653
|
+
if (!key) return [];
|
|
2654
|
+
const [allowlist, entityByAddr] = await Promise.all([
|
|
2655
|
+
fetchEulerLabelsEarnVaultAllowlist(chainId),
|
|
2656
|
+
fetchEulerLabelsEntityNameByAddress(chainId)
|
|
2657
|
+
]);
|
|
2658
|
+
if (!allowlist.size) return [];
|
|
2659
|
+
const assetBytes = key;
|
|
2660
|
+
const ids = [...allowlist];
|
|
2661
|
+
const data = await eulerV2QueryGraphQl(chainId, EARN_VAULTS_QUERY, {
|
|
2662
|
+
asset: assetBytes,
|
|
2663
|
+
ids
|
|
2664
|
+
});
|
|
2665
|
+
const rawRows = data.eulerEarnVaults ?? [];
|
|
2666
|
+
const strategyIds = /* @__PURE__ */ new Set();
|
|
2667
|
+
for (const v of rawRows) {
|
|
2668
|
+
for (const s of v.strategies ?? []) {
|
|
2669
|
+
const sid = normLowerId(s.strategy ?? void 0);
|
|
2670
|
+
if (sid) strategyIds.add(sid);
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
const apyByVault = /* @__PURE__ */ new Map();
|
|
2674
|
+
const sidList = [...strategyIds];
|
|
2675
|
+
const batch = 200;
|
|
2676
|
+
for (let i = 0; i < sidList.length; i += batch) {
|
|
2677
|
+
const chunk = sidList.slice(i, i + batch);
|
|
2678
|
+
const d2 = await eulerV2QueryGraphQl(chainId, STRATEGY_VAULT_APY, {
|
|
2679
|
+
ids: chunk
|
|
2680
|
+
});
|
|
2681
|
+
for (const row of d2.eulerVaults ?? []) {
|
|
2682
|
+
const id = normLowerId(row.id ?? void 0);
|
|
2683
|
+
if (!id) continue;
|
|
2684
|
+
const ray = big(row.state?.supplyApy ?? "0");
|
|
2685
|
+
const sym = (row.symbol ?? "").trim() || "\u2014";
|
|
2686
|
+
const al = normLowerId(row.asset ?? void 0);
|
|
2687
|
+
apyByVault.set(id, { apyRay: ray, symbol: sym, assetLower: al });
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
const dec = Math.max(0, Math.min(36, Math.floor(underlyingDecimals)));
|
|
2691
|
+
const tic = (args.suppliedAssetSymbol ?? "").trim();
|
|
2692
|
+
const out = [];
|
|
2693
|
+
for (const v of rawRows) {
|
|
2694
|
+
const vid = normLowerId(v.id ?? void 0);
|
|
2695
|
+
if (!vid || !allowlist.has(vid)) continue;
|
|
2696
|
+
const curatorLo = normLowerId(v.curator ?? void 0);
|
|
2697
|
+
const curatorName = curatorLo && entityByAddr.has(curatorLo) ? entityByAddr.get(curatorLo) : curatorLo ? `${curatorLo.slice(0, 6)}\u2026${curatorLo.slice(-4)}` : "\u2014";
|
|
2698
|
+
const strategiesRaw = [...v.strategies ?? []];
|
|
2699
|
+
const sumStratAlloc = strategiesRaw.reduce((a, s) => a + big(s.allocatedAssets), 0n);
|
|
2700
|
+
const totalAssets = big(v.totalAssets);
|
|
2701
|
+
const totalAllocatedField = big(v.totalAllocated);
|
|
2702
|
+
let denomForApy = sumStratAlloc;
|
|
2703
|
+
if (denomForApy === 0n) denomForApy = totalAllocatedField;
|
|
2704
|
+
let weightedApyRay = 0n;
|
|
2705
|
+
if (denomForApy > 0n) {
|
|
2706
|
+
let acc = 0n;
|
|
2707
|
+
for (const s of strategiesRaw) {
|
|
2708
|
+
const alloc = big(s.allocatedAssets);
|
|
2709
|
+
const sid = normLowerId(s.strategy ?? void 0);
|
|
2710
|
+
const meta = sid ? apyByVault.get(sid) : void 0;
|
|
2711
|
+
const ray = meta?.apyRay ?? 0n;
|
|
2712
|
+
acc += ray * alloc;
|
|
2713
|
+
}
|
|
2714
|
+
weightedApyRay = acc / denomForApy;
|
|
2715
|
+
}
|
|
2716
|
+
const supplyApyPercentLabel = denomForApy > 0n ? formatEulerRayApyPercent(weightedApyRay) : "0.00%";
|
|
2717
|
+
const deployedForLiquidity = sumStratAlloc > 0n ? sumStratAlloc : totalAllocatedField > 0n ? totalAllocatedField : 0n;
|
|
2718
|
+
const availableWei = totalAssets > deployedForLiquidity ? totalAssets - deployedForLiquidity : 0n;
|
|
2719
|
+
const performanceFee = big(v.performanceFee);
|
|
2720
|
+
const performanceFeePercentLabel = formatPerformanceFeePercent(performanceFee);
|
|
2721
|
+
const vaultName = (v.name ?? "").trim() || "Euler Earn";
|
|
2722
|
+
const stratRows = strategiesRaw.map((s) => {
|
|
2723
|
+
const sid = normLowerId(s.strategy ?? void 0) ?? "";
|
|
2724
|
+
const meta = sid ? apyByVault.get(sid) : void 0;
|
|
2725
|
+
const alloc = big(s.allocatedAssets);
|
|
2726
|
+
const cap = big(s.currentAllocationCap);
|
|
2727
|
+
const pctOfTotal = totalAssets > 0n ? `${(Number(alloc * 10000n / totalAssets) / 100).toFixed(1)}%` : "0.0%";
|
|
2728
|
+
const capUnlimited = isUnboundedEarnStrategyAllocationCap(cap);
|
|
2729
|
+
let capLabel;
|
|
2730
|
+
if (capUnlimited) {
|
|
2731
|
+
capLabel = "\u221E";
|
|
2732
|
+
} else if (cap === 0n) {
|
|
2733
|
+
capLabel = `0${tic ? ` ${tic}` : ""}`;
|
|
2734
|
+
} else {
|
|
2735
|
+
try {
|
|
2736
|
+
capLabel = `${formatUnits(cap, dec)}${tic ? ` ${tic}` : ""}`;
|
|
2737
|
+
} catch {
|
|
2738
|
+
capLabel = cap.toString();
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
let allocHuman;
|
|
2742
|
+
try {
|
|
2743
|
+
allocHuman = `${formatUnits(alloc, dec)}${tic ? ` ${tic}` : ""}`;
|
|
2744
|
+
} catch {
|
|
2745
|
+
allocHuman = alloc.toString();
|
|
2746
|
+
}
|
|
2747
|
+
return {
|
|
2748
|
+
strategyVaultIdLower: sid,
|
|
2749
|
+
strategySymbol: meta?.symbol ?? "\u2014",
|
|
2750
|
+
supplyApyPercentLabel: meta ? formatEulerRayApyPercent(meta.apyRay) : "\u2014",
|
|
2751
|
+
allocatedAssetsWei: alloc,
|
|
2752
|
+
allocatedHumanLabel: allocHuman,
|
|
2753
|
+
allocationPercentOfTvlLabel: pctOfTotal,
|
|
2754
|
+
allocationCapHumanLabel: capLabel,
|
|
2755
|
+
allocationCapUnlimited: capUnlimited
|
|
2756
|
+
};
|
|
2757
|
+
});
|
|
2758
|
+
const cs = checksumHex2(v.id);
|
|
2759
|
+
if (!cs) continue;
|
|
2760
|
+
let totalHuman;
|
|
2761
|
+
let availHuman;
|
|
2762
|
+
try {
|
|
2763
|
+
totalHuman = `${formatUnits(totalAssets, dec)}${tic ? ` ${tic}` : ""}`;
|
|
2764
|
+
availHuman = `${formatUnits(availableWei, dec)}${tic ? ` ${tic}` : ""}`;
|
|
2765
|
+
} catch {
|
|
2766
|
+
totalHuman = totalAssets.toString();
|
|
2767
|
+
availHuman = availableWei.toString();
|
|
2768
|
+
}
|
|
2769
|
+
out.push({
|
|
2770
|
+
vaultIdLower: vid,
|
|
2771
|
+
evaultAddress: cs,
|
|
2772
|
+
vaultName,
|
|
2773
|
+
curatorDisplayName: curatorName,
|
|
2774
|
+
strategyCount: strategiesRaw.length,
|
|
2775
|
+
supplyApyPercentLabel,
|
|
2776
|
+
totalAssetsWei: totalAssets,
|
|
2777
|
+
totalAssetsHumanLabel: totalHuman,
|
|
2778
|
+
availableLiquidityWei: availableWei,
|
|
2779
|
+
availableLiquidityHumanLabel: availHuman,
|
|
2780
|
+
performanceFeePercentLabel,
|
|
2781
|
+
underlyingDecimals: dec,
|
|
2782
|
+
strategies: stratRows
|
|
2783
|
+
});
|
|
2784
|
+
}
|
|
2785
|
+
out.sort((a, b) => {
|
|
2786
|
+
const ap = Number.parseFloat(a.supplyApyPercentLabel.replace("%", "")) || 0;
|
|
2787
|
+
const bp = Number.parseFloat(b.supplyApyPercentLabel.replace("%", "")) || 0;
|
|
2788
|
+
if (bp !== ap) return bp - ap;
|
|
2789
|
+
return a.vaultName.localeCompare(b.vaultName);
|
|
2790
|
+
});
|
|
2791
|
+
return out;
|
|
2792
|
+
}
|
|
2793
|
+
function checksumHex2(raw) {
|
|
2794
|
+
const s = (raw ?? "").trim();
|
|
2795
|
+
if (!s || !isAddress(s)) return null;
|
|
2796
|
+
try {
|
|
2797
|
+
return getAddress(s);
|
|
2798
|
+
} catch {
|
|
2799
|
+
return null;
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
var eulerVaultRiskAbi = parseAbi([
|
|
2803
|
+
"function LTVBorrow(address collateral) view returns (uint16)",
|
|
2804
|
+
"function LTVLiquidation(address collateral) view returns (uint16)"
|
|
2805
|
+
]);
|
|
2806
|
+
var priceOracleAbi = parseAbi([
|
|
2807
|
+
"function getQuote(uint256 inAmount, address base, address quote) view returns (uint256 outAmount)"
|
|
2808
|
+
]);
|
|
2809
|
+
function metaClient(chainId, rpcUrl) {
|
|
2810
|
+
const chain = defineChain({
|
|
2811
|
+
id: chainId,
|
|
2812
|
+
name: "EulerBorrowRisk",
|
|
2813
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
2814
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
2815
|
+
});
|
|
2816
|
+
return createPublicClient({ chain, transport: http(rpcUrl) });
|
|
2817
|
+
}
|
|
2818
|
+
async function fetchEulerV2BorrowPairLtvs(args) {
|
|
2819
|
+
const rpc = (args.rpcUrl ?? "").trim();
|
|
2820
|
+
if (!rpc) return null;
|
|
2821
|
+
try {
|
|
2822
|
+
const client = metaClient(args.chainId, rpc);
|
|
2823
|
+
const coll = getAddress(args.collateralEvault);
|
|
2824
|
+
const bor = getAddress(args.borrowEvault);
|
|
2825
|
+
const [maxLt, liqLt] = await Promise.all([
|
|
2826
|
+
client.readContract({ address: bor, abi: eulerVaultRiskAbi, functionName: "LTVBorrow", args: [coll] }),
|
|
2827
|
+
client.readContract({ address: bor, abi: eulerVaultRiskAbi, functionName: "LTVLiquidation", args: [coll] })
|
|
2828
|
+
]);
|
|
2829
|
+
return { maxLtvBps: Number(maxLt), liquidationLtvBps: Number(liqLt) };
|
|
2830
|
+
} catch {
|
|
2831
|
+
return null;
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
async function fetchEulerV2BorrowOracleQuoteSnapshot(args) {
|
|
2835
|
+
const rpc = (args.rpcUrl ?? "").trim();
|
|
2836
|
+
if (!rpc) return null;
|
|
2837
|
+
if (!isAddress(args.oracle) || !isAddress(args.unitOfAccount)) return null;
|
|
2838
|
+
try {
|
|
2839
|
+
const client = metaClient(args.chainId, rpc);
|
|
2840
|
+
const oracle = getAddress(args.oracle);
|
|
2841
|
+
const uoa = getAddress(args.unitOfAccount);
|
|
2842
|
+
const bAss = getAddress(args.borrowAsset);
|
|
2843
|
+
const cAss = getAddress(args.collateralAsset);
|
|
2844
|
+
const oneBorrow = parseUnits("1", args.borrowDecimals);
|
|
2845
|
+
const collWei = parseUnits(args.collateralAmountHuman, args.collateralDecimals);
|
|
2846
|
+
const [oneBorrowUnitUoAWei, collateralUoAWei] = await Promise.all([
|
|
2847
|
+
client.readContract({
|
|
2848
|
+
address: oracle,
|
|
2849
|
+
abi: priceOracleAbi,
|
|
2850
|
+
functionName: "getQuote",
|
|
2851
|
+
args: [oneBorrow, bAss, uoa]
|
|
2852
|
+
}),
|
|
2853
|
+
collWei > 0n ? client.readContract({
|
|
2854
|
+
address: oracle,
|
|
2855
|
+
abi: priceOracleAbi,
|
|
2856
|
+
functionName: "getQuote",
|
|
2857
|
+
args: [collWei, cAss, uoa]
|
|
2858
|
+
}) : Promise.resolve(0n)
|
|
2859
|
+
]);
|
|
2860
|
+
return { oneBorrowUnitUoAWei, collateralUoAWei };
|
|
2861
|
+
} catch {
|
|
2862
|
+
return null;
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
function estimateBorrowHumanFromLtv(args) {
|
|
2866
|
+
if (args.collateralUoAWei <= 0n || args.oneBorrowUnitUoAWei <= 0n || !(args.ltvPercent > 0)) return "0";
|
|
2867
|
+
const bps = Math.min(1e4, Math.max(0, Math.round(args.ltvPercent * 100)));
|
|
2868
|
+
const debtUoA = args.collateralUoAWei * BigInt(bps) / 10000n;
|
|
2869
|
+
const borrowWei = debtUoA * parseUnits("1", args.borrowDecimals) / args.oneBorrowUnitUoAWei;
|
|
2870
|
+
if (borrowWei <= 0n) return "0";
|
|
2871
|
+
return formatUnits(borrowWei, args.borrowDecimals);
|
|
2872
|
+
}
|
|
2873
|
+
function maxCollateralWeiCappedByBorrowLiquidity(args) {
|
|
2874
|
+
const { walletBalWei, maxBorrowWei, collateralFullUoAWei, oneBorrowUnitUoAWei, ltvPercent, borrowDecimals } = args;
|
|
2875
|
+
if (walletBalWei <= 0n) return 0n;
|
|
2876
|
+
if (maxBorrowWei <= 0n) return 0n;
|
|
2877
|
+
if (!(ltvPercent > 0)) return walletBalWei;
|
|
2878
|
+
if (collateralFullUoAWei <= 0n || oneBorrowUnitUoAWei <= 0n) return walletBalWei;
|
|
2879
|
+
const bps = Math.min(1e4, Math.max(0, Math.round(ltvPercent * 100)));
|
|
2880
|
+
const debtUoA = collateralFullUoAWei * BigInt(bps) / 10000n;
|
|
2881
|
+
const borrowWeiFull = debtUoA * parseUnits("1", borrowDecimals) / oneBorrowUnitUoAWei;
|
|
2882
|
+
if (borrowWeiFull <= 0n) return walletBalWei;
|
|
2883
|
+
if (borrowWeiFull <= maxBorrowWei) return walletBalWei;
|
|
2884
|
+
return walletBalWei * maxBorrowWei / borrowWeiFull;
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
// src/protocols/evm/euler-v2/eulerV2BorrowPositionsLoad.ts
|
|
2888
|
+
var TRACKING_BORROWS = `
|
|
2889
|
+
query EulerTrackingBorrows($id: Bytes!) {
|
|
2890
|
+
trackingActiveAccount(id: $id) {
|
|
2891
|
+
borrows
|
|
2892
|
+
}
|
|
2893
|
+
}`;
|
|
2894
|
+
var VAULTS_FOR_EVAULTS = `
|
|
2895
|
+
query EulerVaultsForBorrows($ids: [ID!]!) {
|
|
2896
|
+
eulerVaults(where: { id_in: $ids }) {
|
|
2897
|
+
id
|
|
2898
|
+
evault
|
|
2899
|
+
evc
|
|
2900
|
+
name
|
|
2901
|
+
symbol
|
|
2902
|
+
asset
|
|
2903
|
+
decimals
|
|
2904
|
+
collaterals
|
|
2905
|
+
}
|
|
2906
|
+
}`;
|
|
2907
|
+
var erc20DecimalsAbi2 = parseAbi(["function decimals() view returns (uint8)"]);
|
|
2908
|
+
var erc4626BalanceAbi = parseAbi(["function balanceOf(address account) view returns (uint256)"]);
|
|
2909
|
+
var erc4626MaxWithdrawAbi2 = parseAbi(["function maxWithdraw(address owner) view returns (uint256)"]);
|
|
2910
|
+
var eulerRiskLtAbi = parseAbi(["function LTVBorrow(address collateral) view returns (uint16)"]);
|
|
2911
|
+
var eulerLiquidityAbi = parseAbi([
|
|
2912
|
+
"function accountLiquidity(address account, bool liquidation) view returns (uint256 collateralValue, uint256 liabilityValue)"
|
|
2913
|
+
]);
|
|
2914
|
+
function metaClient2(chainId, rpcUrl) {
|
|
2915
|
+
const chain = defineChain({
|
|
2916
|
+
id: chainId,
|
|
2917
|
+
name: "EulerBorrowPos",
|
|
2918
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
2919
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
2920
|
+
});
|
|
2921
|
+
return createPublicClient({ chain, transport: http(rpcUrl) });
|
|
2922
|
+
}
|
|
2923
|
+
function parseEulerTrackingBorrowEntry(entry) {
|
|
2924
|
+
const s = (entry ?? "").trim().toLowerCase();
|
|
2925
|
+
if (!s.startsWith("0x")) return null;
|
|
2926
|
+
const hex = s.slice(2);
|
|
2927
|
+
if (hex.length < 80) return null;
|
|
2928
|
+
try {
|
|
2929
|
+
const subAccount = getAddress(`0x${hex.slice(0, 40)}`);
|
|
2930
|
+
const borrowVault = getAddress(`0x${hex.slice(40, 80)}`);
|
|
2931
|
+
return { subAccount, borrowVault };
|
|
2932
|
+
} catch {
|
|
2933
|
+
return null;
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
async function fetchEulerV2TrackingBorrowEntries(args) {
|
|
2937
|
+
const id = args.mainAddress.toLowerCase();
|
|
2938
|
+
const data = await eulerV2QueryGraphQl(
|
|
2939
|
+
args.chainId,
|
|
2940
|
+
TRACKING_BORROWS,
|
|
2941
|
+
{ id }
|
|
2942
|
+
);
|
|
2943
|
+
const raw = data.trackingActiveAccount?.borrows ?? [];
|
|
2944
|
+
return raw.filter((x) => typeof x === "string" && x.trim().length > 0);
|
|
2945
|
+
}
|
|
2946
|
+
async function pickCollateralEvault(args) {
|
|
2947
|
+
const cands = (args.collaterals ?? []).map((c) => (c ?? "").trim().toLowerCase()).filter((c) => c.startsWith("0x") && isAddress(c));
|
|
2948
|
+
const uniq = [...new Set(cands)];
|
|
2949
|
+
for (const low of uniq) {
|
|
2950
|
+
try {
|
|
2951
|
+
const coll = getAddress(low);
|
|
2952
|
+
const lt = await args.client.readContract({
|
|
2953
|
+
address: args.borrowVault,
|
|
2954
|
+
abi: eulerRiskLtAbi,
|
|
2955
|
+
functionName: "LTVBorrow",
|
|
2956
|
+
args: [coll]
|
|
2957
|
+
});
|
|
2958
|
+
if (Number(lt) === 0) continue;
|
|
2959
|
+
const bal = await args.client.readContract({
|
|
2960
|
+
address: coll,
|
|
2961
|
+
abi: erc4626BalanceAbi,
|
|
2962
|
+
functionName: "balanceOf",
|
|
2963
|
+
args: [args.subAccount]
|
|
2964
|
+
});
|
|
2965
|
+
if (bal > 0n) return coll;
|
|
2966
|
+
} catch {
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
for (const low of uniq) {
|
|
2970
|
+
try {
|
|
2971
|
+
const coll = getAddress(low);
|
|
2972
|
+
const lt = await args.client.readContract({
|
|
2973
|
+
address: args.borrowVault,
|
|
2974
|
+
abi: eulerRiskLtAbi,
|
|
2975
|
+
functionName: "LTVBorrow",
|
|
2976
|
+
args: [coll]
|
|
2977
|
+
});
|
|
2978
|
+
if (Number(lt) > 0) return coll;
|
|
2979
|
+
} catch {
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
if (uniq.length) {
|
|
2983
|
+
try {
|
|
2984
|
+
return getAddress(uniq[0]);
|
|
2985
|
+
} catch {
|
|
2986
|
+
return null;
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
return null;
|
|
2990
|
+
}
|
|
2991
|
+
async function loadEulerV2BorrowPositionsForOwner(args) {
|
|
2992
|
+
const rpc = args.rpcUrl.trim();
|
|
2993
|
+
if (!rpc) return [];
|
|
2994
|
+
const [entries, depositEntries] = await Promise.all([
|
|
2995
|
+
fetchEulerV2TrackingBorrowEntries({ chainId: args.chainId, mainAddress: args.mainAddress }),
|
|
2996
|
+
fetchEulerV2TrackingDepositEntries({ chainId: args.chainId, mainAddress: args.mainAddress })
|
|
2997
|
+
]);
|
|
2998
|
+
const pairKey = (sub, vault) => `${sub.toLowerCase()}-${vault.toLowerCase()}`;
|
|
2999
|
+
const seenPairs = /* @__PURE__ */ new Set();
|
|
3000
|
+
const pairs = [];
|
|
3001
|
+
const pushPair = (sub, vault) => {
|
|
3002
|
+
const k = pairKey(sub, vault);
|
|
3003
|
+
if (seenPairs.has(k)) return;
|
|
3004
|
+
seenPairs.add(k);
|
|
3005
|
+
pairs.push({ subAccount: sub, borrowVault: vault });
|
|
3006
|
+
};
|
|
3007
|
+
for (const e of entries) {
|
|
3008
|
+
const p = parseEulerTrackingBorrowEntry(e);
|
|
3009
|
+
if (p) pushPair(p.subAccount, p.borrowVault);
|
|
3010
|
+
}
|
|
3011
|
+
const client = metaClient2(args.chainId, rpc);
|
|
3012
|
+
const debtAbi = parseAbi(["function debtOf(address account) view returns (uint256)"]);
|
|
3013
|
+
for (const e of depositEntries) {
|
|
3014
|
+
const p = parseEulerTrackingBorrowEntry(e);
|
|
3015
|
+
if (!p) continue;
|
|
3016
|
+
if (seenPairs.has(pairKey(p.subAccount, p.borrowVault))) continue;
|
|
3017
|
+
let debtWei = 0n;
|
|
3018
|
+
try {
|
|
3019
|
+
debtWei = await client.readContract({
|
|
3020
|
+
address: p.borrowVault,
|
|
3021
|
+
abi: debtAbi,
|
|
3022
|
+
functionName: "debtOf",
|
|
3023
|
+
args: [p.subAccount]
|
|
3024
|
+
});
|
|
3025
|
+
} catch {
|
|
3026
|
+
continue;
|
|
3027
|
+
}
|
|
3028
|
+
if (debtWei === 0n) continue;
|
|
3029
|
+
pushPair(p.subAccount, p.borrowVault);
|
|
3030
|
+
}
|
|
3031
|
+
if (!pairs.length) return [];
|
|
3032
|
+
const vaultIds = [...new Set(pairs.map((x) => x.borrowVault.toLowerCase()))];
|
|
3033
|
+
const vaultData = await eulerV2QueryGraphQl(args.chainId, VAULTS_FOR_EVAULTS, { ids: vaultIds });
|
|
3034
|
+
const byEvault = /* @__PURE__ */ new Map();
|
|
3035
|
+
for (const v of vaultData.eulerVaults ?? []) {
|
|
3036
|
+
const ev = (v.evault ?? "").trim().toLowerCase();
|
|
3037
|
+
if (ev) byEvault.set(ev, v);
|
|
3038
|
+
}
|
|
3039
|
+
const evcAbi5 = parseAbi(["function EVC() view returns (address)"]);
|
|
3040
|
+
const out = [];
|
|
3041
|
+
const t = Date.now();
|
|
3042
|
+
for (const { subAccount, borrowVault } of pairs) {
|
|
3043
|
+
let debtWei = 0n;
|
|
3044
|
+
try {
|
|
3045
|
+
debtWei = await client.readContract({
|
|
3046
|
+
address: borrowVault,
|
|
3047
|
+
abi: debtAbi,
|
|
3048
|
+
functionName: "debtOf",
|
|
3049
|
+
args: [subAccount]
|
|
3050
|
+
});
|
|
3051
|
+
} catch {
|
|
3052
|
+
}
|
|
3053
|
+
const vrow = byEvault.get(borrowVault.toLowerCase());
|
|
3054
|
+
const decRaw = Number((vrow?.decimals ?? "18").toString().trim() || "18");
|
|
3055
|
+
const decimals = Number.isFinite(decRaw) && decRaw >= 0 && decRaw <= 36 ? decRaw : 18;
|
|
3056
|
+
let assetLow = (vrow?.asset ?? "").trim().toLowerCase();
|
|
3057
|
+
if (!assetLow || !isAddress(assetLow)) {
|
|
3058
|
+
try {
|
|
3059
|
+
const a = await client.readContract({
|
|
3060
|
+
address: borrowVault,
|
|
3061
|
+
abi: parseAbi(["function asset() view returns (address)"]),
|
|
3062
|
+
functionName: "asset"
|
|
3063
|
+
});
|
|
3064
|
+
assetLow = getAddress(a).toLowerCase();
|
|
3065
|
+
} catch {
|
|
3066
|
+
assetLow = "";
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
let decFinal = decimals;
|
|
3070
|
+
if (assetLow && isAddress(assetLow)) {
|
|
3071
|
+
try {
|
|
3072
|
+
const d = await client.readContract({
|
|
3073
|
+
address: getAddress(assetLow),
|
|
3074
|
+
abi: erc20DecimalsAbi2,
|
|
3075
|
+
functionName: "decimals"
|
|
3076
|
+
});
|
|
3077
|
+
const n = Number(d);
|
|
3078
|
+
if (Number.isFinite(n) && n >= 0 && n <= 36) decFinal = n;
|
|
3079
|
+
} catch {
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
const debtHuman = formatUnits(debtWei, decFinal);
|
|
3083
|
+
const collateralVault = await pickCollateralEvault({
|
|
3084
|
+
client,
|
|
3085
|
+
borrowVault,
|
|
3086
|
+
subAccount,
|
|
3087
|
+
collaterals: vrow?.collaterals ?? null
|
|
3088
|
+
});
|
|
3089
|
+
if (debtWei === 0n) {
|
|
3090
|
+
if (!collateralVault) continue;
|
|
3091
|
+
let maxWithdrawLeft = 0n;
|
|
3092
|
+
try {
|
|
3093
|
+
maxWithdrawLeft = await client.readContract({
|
|
3094
|
+
address: collateralVault,
|
|
3095
|
+
abi: erc4626MaxWithdrawAbi2,
|
|
3096
|
+
functionName: "maxWithdraw",
|
|
3097
|
+
args: [subAccount]
|
|
3098
|
+
});
|
|
3099
|
+
} catch {
|
|
3100
|
+
maxWithdrawLeft = 0n;
|
|
3101
|
+
}
|
|
3102
|
+
let collateralShares = 0n;
|
|
3103
|
+
if (maxWithdrawLeft === 0n) {
|
|
3104
|
+
try {
|
|
3105
|
+
collateralShares = await client.readContract({
|
|
3106
|
+
address: collateralVault,
|
|
3107
|
+
abi: erc4626BalanceAbi,
|
|
3108
|
+
functionName: "balanceOf",
|
|
3109
|
+
args: [subAccount]
|
|
3110
|
+
});
|
|
3111
|
+
} catch {
|
|
3112
|
+
collateralShares = 0n;
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
if (maxWithdrawLeft === 0n && collateralShares === 0n) continue;
|
|
3116
|
+
}
|
|
3117
|
+
let collateralAssetAddressLower = null;
|
|
3118
|
+
let collateralAssetDecimals;
|
|
3119
|
+
let collateralUnderlyingSymbol = null;
|
|
3120
|
+
if (collateralVault) {
|
|
3121
|
+
try {
|
|
3122
|
+
const assetAddr = await client.readContract({
|
|
3123
|
+
address: collateralVault,
|
|
3124
|
+
abi: parseAbi(["function asset() view returns (address)"]),
|
|
3125
|
+
functionName: "asset"
|
|
3126
|
+
});
|
|
3127
|
+
const cLow = getAddress(assetAddr).toLowerCase();
|
|
3128
|
+
collateralAssetAddressLower = cLow;
|
|
3129
|
+
const cd = await client.readContract({
|
|
3130
|
+
address: getAddress(cLow),
|
|
3131
|
+
abi: erc20DecimalsAbi2,
|
|
3132
|
+
functionName: "decimals"
|
|
3133
|
+
});
|
|
3134
|
+
const cn = Number(cd);
|
|
3135
|
+
if (Number.isFinite(cn) && cn >= 0 && cn <= 36) collateralAssetDecimals = cn;
|
|
3136
|
+
try {
|
|
3137
|
+
const sym = await client.readContract({
|
|
3138
|
+
address: getAddress(cLow),
|
|
3139
|
+
abi: parseAbi(["function symbol() view returns (string)"]),
|
|
3140
|
+
functionName: "symbol"
|
|
3141
|
+
});
|
|
3142
|
+
const s = typeof sym === "string" ? sym.trim() : "";
|
|
3143
|
+
if (s) collateralUnderlyingSymbol = s;
|
|
3144
|
+
} catch {
|
|
3145
|
+
}
|
|
3146
|
+
} catch {
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
let maxLtvBps = null;
|
|
3150
|
+
let liquidationLtvBps = null;
|
|
3151
|
+
if (collateralVault) {
|
|
3152
|
+
const risk = await fetchEulerV2BorrowPairLtvs({
|
|
3153
|
+
chainId: args.chainId,
|
|
3154
|
+
rpcUrl: rpc,
|
|
3155
|
+
borrowEvault: borrowVault,
|
|
3156
|
+
collateralEvault: collateralVault
|
|
3157
|
+
});
|
|
3158
|
+
if (risk) {
|
|
3159
|
+
maxLtvBps = risk.maxLtvBps;
|
|
3160
|
+
liquidationLtvBps = risk.liquidationLtvBps;
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
3163
|
+
let currentLtvPercent = null;
|
|
3164
|
+
try {
|
|
3165
|
+
const [collV, liabV] = await client.readContract({
|
|
3166
|
+
address: borrowVault,
|
|
3167
|
+
abi: eulerLiquidityAbi,
|
|
3168
|
+
functionName: "accountLiquidity",
|
|
3169
|
+
args: [subAccount, false]
|
|
3170
|
+
});
|
|
3171
|
+
if (collV > 0n && liabV > 0n) {
|
|
3172
|
+
currentLtvPercent = Number(liabV * 10000n / collV) / 100;
|
|
3173
|
+
}
|
|
3174
|
+
} catch {
|
|
3175
|
+
}
|
|
3176
|
+
let evc = (vrow?.evc ?? "").trim() ? getAddress(vrow.evc.trim()) : null;
|
|
3177
|
+
if (!evc) {
|
|
3178
|
+
try {
|
|
3179
|
+
const e = await client.readContract({
|
|
3180
|
+
address: borrowVault,
|
|
3181
|
+
abi: evcAbi5,
|
|
3182
|
+
functionName: "EVC"
|
|
3183
|
+
});
|
|
3184
|
+
evc = getAddress(e);
|
|
3185
|
+
} catch {
|
|
3186
|
+
evc = null;
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
const marketName = [(vrow?.symbol ?? "").trim(), (vrow?.name ?? "").trim()].filter(Boolean).join(" \xB7 ") || `Borrow ${borrowVault.slice(0, 10)}\u2026`;
|
|
3190
|
+
out.push({
|
|
3191
|
+
id: `borrow-${args.chainId}-${subAccount.toLowerCase()}-${borrowVault.toLowerCase()}`,
|
|
3192
|
+
chainId: args.chainId,
|
|
3193
|
+
vaultId: (vrow?.id ?? borrowVault).toString(),
|
|
3194
|
+
evaultAddress: borrowVault,
|
|
3195
|
+
marketName,
|
|
3196
|
+
underlyingSymbol: (vrow?.symbol ?? "\u2014").toString().trim() || "\u2014",
|
|
3197
|
+
amountHuman: debtHuman,
|
|
3198
|
+
createdAtMs: t,
|
|
3199
|
+
signRequestId: null,
|
|
3200
|
+
positionKind: "borrow",
|
|
3201
|
+
subAccountAddress: subAccount,
|
|
3202
|
+
collateralEvaultAddress: collateralVault,
|
|
3203
|
+
evcAddress: evc,
|
|
3204
|
+
borrowAssetAddressLower: assetLow || null,
|
|
3205
|
+
borrowAssetDecimals: decFinal,
|
|
3206
|
+
borrowDebtHuman: debtHuman,
|
|
3207
|
+
collateralAssetAddressLower,
|
|
3208
|
+
collateralAssetDecimals,
|
|
3209
|
+
collateralUnderlyingSymbol,
|
|
3210
|
+
currentLtvPercent,
|
|
3211
|
+
maxLtvBps,
|
|
3212
|
+
liquidationLtvBps
|
|
3213
|
+
});
|
|
3214
|
+
}
|
|
3215
|
+
return out.sort((a, b) => (a.marketName || "").localeCompare(b.marketName || ""));
|
|
3216
|
+
}
|
|
3217
|
+
async function fetchEulerV2BorrowDebtWei(args) {
|
|
3218
|
+
const rpc = args.rpcUrl.trim();
|
|
3219
|
+
if (!rpc) return 0n;
|
|
3220
|
+
const client = metaClient2(args.chainId, rpc);
|
|
3221
|
+
const debtAbi = parseAbi(["function debtOf(address account) view returns (uint256)"]);
|
|
3222
|
+
try {
|
|
3223
|
+
return await client.readContract({
|
|
3224
|
+
address: args.borrowVault,
|
|
3225
|
+
abi: debtAbi,
|
|
3226
|
+
functionName: "debtOf",
|
|
3227
|
+
args: [args.subAccount]
|
|
3228
|
+
});
|
|
3229
|
+
} catch {
|
|
3230
|
+
return 0n;
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
var VAULTS_FOR_EVAULTS2 = `
|
|
3234
|
+
query EulerVaultsForSupply($ids: [ID!]!) {
|
|
3235
|
+
eulerVaults(where: { id_in: $ids }) {
|
|
3236
|
+
id
|
|
3237
|
+
evault
|
|
3238
|
+
name
|
|
3239
|
+
symbol
|
|
3240
|
+
asset
|
|
3241
|
+
decimals
|
|
3242
|
+
}
|
|
3243
|
+
}`;
|
|
3244
|
+
var vaultSupplyAbi = parseAbi([
|
|
3245
|
+
"function balanceOf(address account) view returns (uint256)",
|
|
3246
|
+
"function convertToAssets(uint256 shares) view returns (uint256)",
|
|
3247
|
+
"function asset() view returns (address)"
|
|
3248
|
+
]);
|
|
3249
|
+
var debtOfAbi = parseAbi(["function debtOf(address account) view returns (uint256)"]);
|
|
3250
|
+
function metaClient3(chainId, rpcUrl) {
|
|
3251
|
+
const chain = defineChain({
|
|
3252
|
+
id: chainId,
|
|
3253
|
+
name: "EulerLendSupply",
|
|
3254
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
3255
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
3256
|
+
});
|
|
3257
|
+
return createPublicClient({ chain, transport: http(rpcUrl) });
|
|
3258
|
+
}
|
|
3259
|
+
async function readSupplyUnderlyingWei(client, vault, shareOwner) {
|
|
3260
|
+
try {
|
|
3261
|
+
const shares = await client.readContract({
|
|
3262
|
+
address: vault,
|
|
3263
|
+
abi: vaultSupplyAbi,
|
|
3264
|
+
functionName: "balanceOf",
|
|
3265
|
+
args: [shareOwner]
|
|
3266
|
+
});
|
|
3267
|
+
if (shares === 0n) return null;
|
|
3268
|
+
const assets = await client.readContract({
|
|
3269
|
+
address: vault,
|
|
3270
|
+
abi: vaultSupplyAbi,
|
|
3271
|
+
functionName: "convertToAssets",
|
|
3272
|
+
args: [shares]
|
|
3273
|
+
});
|
|
3274
|
+
if (assets === 0n) return null;
|
|
3275
|
+
const asset = await client.readContract({
|
|
3276
|
+
address: vault,
|
|
3277
|
+
abi: vaultSupplyAbi,
|
|
3278
|
+
functionName: "asset"
|
|
3279
|
+
});
|
|
3280
|
+
return { asset: getAddress(asset), wei: assets };
|
|
3281
|
+
} catch {
|
|
3282
|
+
return null;
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
async function loadEulerV2LendSupplyPositionsForOwner(args) {
|
|
3286
|
+
const rpc = args.rpcUrl.trim();
|
|
3287
|
+
if (!rpc) return [];
|
|
3288
|
+
if (!eulerV2GoldskyUrlForChain(args.chainId)) return [];
|
|
3289
|
+
const [entries, earnVaultAllowlist, gasAliases] = await Promise.all([
|
|
3290
|
+
fetchEulerV2TrackingDepositEntries({ chainId: args.chainId, mainAddress: args.mainAddress }),
|
|
3291
|
+
fetchEulerLabelsEarnVaultAllowlist(args.chainId),
|
|
3292
|
+
eulerWrappedGasTokenAliasesLower(args.chainId)
|
|
3293
|
+
]);
|
|
3294
|
+
const pairs = [];
|
|
3295
|
+
for (const e of entries) {
|
|
3296
|
+
const p = parseEulerTrackingBorrowEntry(e);
|
|
3297
|
+
if (p) pairs.push({ subAccount: p.subAccount, evault: p.borrowVault });
|
|
3298
|
+
}
|
|
3299
|
+
if (!pairs.length) return [];
|
|
3300
|
+
const vaultIds = [...new Set(pairs.map((x) => x.evault.toLowerCase()))];
|
|
3301
|
+
const vaultData = await eulerV2QueryGraphQl(args.chainId, VAULTS_FOR_EVAULTS2, { ids: vaultIds });
|
|
3302
|
+
const byEvault = /* @__PURE__ */ new Map();
|
|
3303
|
+
for (const v of vaultData.eulerVaults ?? []) {
|
|
3304
|
+
const ev = (v.evault ?? "").trim().toLowerCase();
|
|
3305
|
+
if (ev) byEvault.set(ev, v);
|
|
3306
|
+
}
|
|
3307
|
+
const client = metaClient3(args.chainId, rpc);
|
|
3308
|
+
const t = Date.now();
|
|
3309
|
+
const out = [];
|
|
3310
|
+
const seenPair = /* @__PURE__ */ new Set();
|
|
3311
|
+
for (const { subAccount, evault } of pairs) {
|
|
3312
|
+
const pairKey = `${subAccount.toLowerCase()}-${evault.toLowerCase()}`;
|
|
3313
|
+
if (seenPair.has(pairKey)) continue;
|
|
3314
|
+
seenPair.add(pairKey);
|
|
3315
|
+
const supply = await readSupplyUnderlyingWei(client, evault, subAccount);
|
|
3316
|
+
if (!supply) continue;
|
|
3317
|
+
let liabilityDebtWei = 0n;
|
|
3318
|
+
try {
|
|
3319
|
+
liabilityDebtWei = await client.readContract({
|
|
3320
|
+
address: evault,
|
|
3321
|
+
abi: debtOfAbi,
|
|
3322
|
+
functionName: "debtOf",
|
|
3323
|
+
args: [subAccount]
|
|
3324
|
+
});
|
|
3325
|
+
} catch {
|
|
3326
|
+
liabilityDebtWei = 0n;
|
|
3327
|
+
}
|
|
3328
|
+
if (liabilityDebtWei > 0n) continue;
|
|
3329
|
+
const vrow = byEvault.get(evault.toLowerCase());
|
|
3330
|
+
const isEarn = earnVaultAllowlist.has(evault.toLowerCase());
|
|
3331
|
+
const positionKind = isEarn ? "earn" : "lend";
|
|
3332
|
+
const underlyingSymbol = (vrow?.symbol ?? "\u2014").toString().trim() || "\u2014";
|
|
3333
|
+
const marketName = [(vrow?.symbol ?? "").trim(), (vrow?.name ?? "").trim()].filter(Boolean).join(" \xB7 ") || `${isEarn ? "Earn" : "Lend"} ${evault.slice(0, 10)}\u2026`;
|
|
3334
|
+
let evChecksummed;
|
|
3335
|
+
try {
|
|
3336
|
+
evChecksummed = getAddress(evault);
|
|
3337
|
+
} catch {
|
|
3338
|
+
continue;
|
|
3339
|
+
}
|
|
3340
|
+
let vaultMeta;
|
|
3341
|
+
try {
|
|
3342
|
+
vaultMeta = await fetchEulerVaultUnderlyingMeta({
|
|
3343
|
+
rpcUrl: rpc,
|
|
3344
|
+
chainId: args.chainId,
|
|
3345
|
+
evault: evChecksummed
|
|
3346
|
+
});
|
|
3347
|
+
} catch {
|
|
3348
|
+
continue;
|
|
3349
|
+
}
|
|
3350
|
+
const decimals = clampEulerUnderlyingDecimalsForEulerUi({
|
|
3351
|
+
fetchedDecimals: vaultMeta.decimals,
|
|
3352
|
+
underlyingAssetLower: vaultMeta.asset.toLowerCase(),
|
|
3353
|
+
marketName,
|
|
3354
|
+
underlyingSymbol,
|
|
3355
|
+
wrappedGasAliasesLower: gasAliases
|
|
3356
|
+
});
|
|
3357
|
+
const amountHuman = formatUnits(supply.wei, decimals);
|
|
3358
|
+
out.push({
|
|
3359
|
+
id: `${positionKind}-supply-${args.chainId}-${subAccount.toLowerCase()}-${evault.toLowerCase()}`,
|
|
3360
|
+
chainId: args.chainId,
|
|
3361
|
+
vaultId: (vrow?.id ?? evault).toString(),
|
|
3362
|
+
evaultAddress: evault,
|
|
3363
|
+
marketName,
|
|
3364
|
+
underlyingSymbol,
|
|
3365
|
+
amountHuman,
|
|
3366
|
+
underlyingAssetsWei: supply.wei.toString(),
|
|
3367
|
+
underlyingAssetAddressLower: vaultMeta.asset.toLowerCase(),
|
|
3368
|
+
createdAtMs: t,
|
|
3369
|
+
signRequestId: null,
|
|
3370
|
+
positionKind,
|
|
3371
|
+
subAccountAddress: subAccount,
|
|
3372
|
+
underlyingAssetDecimals: decimals
|
|
3373
|
+
});
|
|
3374
|
+
}
|
|
3375
|
+
return out.sort((a, b) => (a.marketName || "").localeCompare(b.marketName || ""));
|
|
3376
|
+
}
|
|
3377
|
+
function mergeEulerV2PositionsTabRows(args) {
|
|
3378
|
+
const main = args.mainAddressLower.trim().toLowerCase();
|
|
3379
|
+
const keyOf = (p) => {
|
|
3380
|
+
const kind = p.positionKind ?? "lend";
|
|
3381
|
+
if (kind === "borrow") return p.id;
|
|
3382
|
+
const ev = p.evaultAddress.trim().toLowerCase();
|
|
3383
|
+
const sub = (p.subAccountAddress ?? main).trim().toLowerCase();
|
|
3384
|
+
return `supply|${ev}|${sub}`;
|
|
3385
|
+
};
|
|
3386
|
+
const chainKeys = new Set(args.chainSupply.map(keyOf));
|
|
3387
|
+
const sessionFiltered = args.session.filter((s) => !chainKeys.has(keyOf(s)));
|
|
3388
|
+
return [...args.borrow, ...args.chainSupply, ...sessionFiltered];
|
|
3389
|
+
}
|
|
3390
|
+
var REUL_LOCK_DAY_SEC = 86400n;
|
|
3391
|
+
var REUL_FULL_VEST_SEC = 180n * REUL_LOCK_DAY_SEC;
|
|
3392
|
+
var rewardTokenReadAbi = parseAbi([
|
|
3393
|
+
"function getLockedAmounts(address account) view returns (uint256[] lockTimestamps, uint256[] amounts)",
|
|
3394
|
+
"function getWithdrawAmountsByLockTimestamp(address account, uint256 lockTimestamp) view returns (uint256 accountAmount, uint256 remainderAmount)"
|
|
3395
|
+
]);
|
|
3396
|
+
var eulerReulUnlockAbi = parseAbi([
|
|
3397
|
+
"function withdrawToByLockTimestamps(address account, uint256[] lockTimestamps, bool allowRemainderLoss) returns (bool)"
|
|
3398
|
+
]);
|
|
3399
|
+
async function fetchEulerReulVestingTranches(args) {
|
|
3400
|
+
const rpc = args.rpcUrl.trim();
|
|
3401
|
+
if (!rpc) return [];
|
|
3402
|
+
const reul = getAddress(args.reulToken);
|
|
3403
|
+
const user = getAddress(args.user);
|
|
3404
|
+
const ch = defineChain({
|
|
3405
|
+
id: args.chainId,
|
|
3406
|
+
name: "ReulVest",
|
|
3407
|
+
nativeCurrency: { decimals: 18, name: "Ether", symbol: "ETH" },
|
|
3408
|
+
rpcUrls: { default: { http: [rpc] } }
|
|
3409
|
+
});
|
|
3410
|
+
const client = createPublicClient({ chain: ch, transport: http(rpc) });
|
|
3411
|
+
const [timestamps, amounts] = await client.readContract({
|
|
3412
|
+
address: reul,
|
|
3413
|
+
abi: rewardTokenReadAbi,
|
|
3414
|
+
functionName: "getLockedAmounts",
|
|
3415
|
+
args: [user]
|
|
3416
|
+
});
|
|
3417
|
+
const out = [];
|
|
3418
|
+
for (let i = 0; i < timestamps.length; i++) {
|
|
3419
|
+
const lockTs = timestamps[i];
|
|
3420
|
+
const lockedAmt = amounts[i];
|
|
3421
|
+
if (lockedAmt === 0n) continue;
|
|
3422
|
+
const [unlockToWalletWei, remainderWei] = await client.readContract({
|
|
3423
|
+
address: reul,
|
|
3424
|
+
abi: rewardTokenReadAbi,
|
|
3425
|
+
functionName: "getWithdrawAmountsByLockTimestamp",
|
|
3426
|
+
args: [user, lockTs]
|
|
3427
|
+
});
|
|
3428
|
+
out.push({
|
|
3429
|
+
reulToken: reul,
|
|
3430
|
+
lockTimestampSec: lockTs,
|
|
3431
|
+
lockedAmountWei: lockedAmt,
|
|
3432
|
+
unlockToWalletWei,
|
|
3433
|
+
remainderWei,
|
|
3434
|
+
fullVestTimestampSec: lockTs + REUL_FULL_VEST_SEC,
|
|
3435
|
+
isFullyVested: remainderWei === 0n
|
|
3436
|
+
});
|
|
3437
|
+
}
|
|
3438
|
+
return out;
|
|
3439
|
+
}
|
|
3440
|
+
function encodeEulerReulWithdrawToByLockTimestampsData(args) {
|
|
3441
|
+
const recipient = getAddress(args.recipient);
|
|
3442
|
+
if (args.lockTimestampsSec.length === 0) throw new Error("No rEUL lock timestamps to unlock.");
|
|
3443
|
+
return encodeFunctionData({
|
|
3444
|
+
abi: eulerReulUnlockAbi,
|
|
3445
|
+
functionName: "withdrawToByLockTimestamps",
|
|
3446
|
+
args: [recipient, [...args.lockTimestampsSec], args.allowRemainderLoss]
|
|
3447
|
+
});
|
|
3448
|
+
}
|
|
3449
|
+
var EULER_REUL_UNLOCK_GAS_FALLBACK = 500000n;
|
|
3450
|
+
|
|
3451
|
+
// src/chains/evm/coingecko.ts
|
|
3452
|
+
var COINGECKO_PLATFORM_BY_CHAIN_ID = {
|
|
3453
|
+
"1": "ethereum",
|
|
3454
|
+
"56": "binance-smart-chain",
|
|
3455
|
+
"137": "polygon-pos",
|
|
3456
|
+
"42161": "arbitrum-one",
|
|
3457
|
+
"10": "optimistic-ethereum",
|
|
3458
|
+
"43114": "avalanche",
|
|
3459
|
+
"8453": "base",
|
|
3460
|
+
"324": "zk-sync-era",
|
|
3461
|
+
"42220": "celo",
|
|
3462
|
+
"250": "fantom",
|
|
3463
|
+
"100": "gnosis",
|
|
3464
|
+
"204": "op-bnb",
|
|
3465
|
+
"534352": "scroll",
|
|
3466
|
+
"5000": "mantle",
|
|
3467
|
+
"169": "manta-pacific",
|
|
3468
|
+
"1116": "core",
|
|
3469
|
+
"30": "rootstock",
|
|
3470
|
+
"288": "boba",
|
|
3471
|
+
"1088": "metis-andromeda",
|
|
3472
|
+
"34443": "mode",
|
|
3473
|
+
"80084": "berachain",
|
|
3474
|
+
"146": "sonic",
|
|
3475
|
+
"60808": "bob-network",
|
|
3476
|
+
"80094": "berachain",
|
|
3477
|
+
"130": "unichain",
|
|
3478
|
+
"57073": "ink",
|
|
3479
|
+
"999": "hyperevm",
|
|
3480
|
+
"239": "tac",
|
|
3481
|
+
"9745": "plasma",
|
|
3482
|
+
"1923": "swellchain",
|
|
3483
|
+
"59144": "linea",
|
|
3484
|
+
"81457": "blast",
|
|
3485
|
+
"7777777": "zora"
|
|
3486
|
+
};
|
|
3487
|
+
|
|
3488
|
+
// src/protocols/evm/euler-v2/eulerV2PortfolioUsd.ts
|
|
3489
|
+
var TRACKING_ACCOUNT = `
|
|
3490
|
+
query EulerTrackingAccount($id: Bytes!) {
|
|
3491
|
+
trackingActiveAccount(id: $id) {
|
|
3492
|
+
deposits
|
|
3493
|
+
borrows
|
|
3494
|
+
}
|
|
3495
|
+
}`;
|
|
3496
|
+
var vaultSupplyAbi2 = parseAbi([
|
|
3497
|
+
"function balanceOf(address account) view returns (uint256)",
|
|
3498
|
+
"function convertToAssets(uint256 shares) view returns (uint256)",
|
|
3499
|
+
"function asset() view returns (address)"
|
|
3500
|
+
]);
|
|
3501
|
+
var erc20DecimalsAbi3 = parseAbi(["function decimals() view returns (uint8)"]);
|
|
3502
|
+
var debtOfAbi2 = parseAbi(["function debtOf(address account) view returns (uint256)"]);
|
|
3503
|
+
function publicClient(chainId, rpcUrl) {
|
|
3504
|
+
const ch = defineChain({
|
|
3505
|
+
id: chainId,
|
|
3506
|
+
name: "EulerPortfolio",
|
|
3507
|
+
nativeCurrency: { decimals: 18, name: "x", symbol: "x" },
|
|
3508
|
+
rpcUrls: { default: { http: [rpcUrl] } }
|
|
3509
|
+
});
|
|
3510
|
+
return createPublicClient({ chain: ch, transport: http(rpcUrl) });
|
|
3511
|
+
}
|
|
3512
|
+
async function gqlTrackingAccount(chainId, mainLower) {
|
|
3513
|
+
if (!eulerV2GoldskyUrlForChain(chainId)) {
|
|
3514
|
+
return { deposits: [], borrows: [] };
|
|
3515
|
+
}
|
|
3516
|
+
const data = await eulerV2QueryGraphQl(chainId, TRACKING_ACCOUNT, { id: mainLower });
|
|
3517
|
+
const a = data.trackingActiveAccount;
|
|
3518
|
+
const dep = (a?.deposits ?? []).filter((x) => typeof x === "string" && x.trim().length > 0);
|
|
3519
|
+
const bor = (a?.borrows ?? []).filter((x) => typeof x === "string" && x.trim().length > 0);
|
|
3520
|
+
return { deposits: dep, borrows: bor };
|
|
3521
|
+
}
|
|
3522
|
+
async function decimalsForAsset(client, asset) {
|
|
3523
|
+
try {
|
|
3524
|
+
const d = await client.readContract({
|
|
3525
|
+
address: asset,
|
|
3526
|
+
abi: erc20DecimalsAbi3,
|
|
3527
|
+
functionName: "decimals"
|
|
3528
|
+
});
|
|
3529
|
+
const n = Number(d);
|
|
3530
|
+
if (Number.isFinite(n) && n >= 0 && n <= 36) return n;
|
|
3531
|
+
} catch {
|
|
3532
|
+
}
|
|
3533
|
+
return 18;
|
|
3534
|
+
}
|
|
3535
|
+
async function readSupplyUnderlyingWei2(client, vault, subAccount) {
|
|
3536
|
+
try {
|
|
3537
|
+
const shares = await client.readContract({
|
|
3538
|
+
address: vault,
|
|
3539
|
+
abi: vaultSupplyAbi2,
|
|
3540
|
+
functionName: "balanceOf",
|
|
3541
|
+
args: [subAccount]
|
|
3542
|
+
});
|
|
3543
|
+
if (shares === 0n) return null;
|
|
3544
|
+
const assets = await client.readContract({
|
|
3545
|
+
address: vault,
|
|
3546
|
+
abi: vaultSupplyAbi2,
|
|
3547
|
+
functionName: "convertToAssets",
|
|
3548
|
+
args: [shares]
|
|
3549
|
+
});
|
|
3550
|
+
if (assets === 0n) return null;
|
|
3551
|
+
const asset = await client.readContract({
|
|
3552
|
+
address: vault,
|
|
3553
|
+
abi: vaultSupplyAbi2,
|
|
3554
|
+
functionName: "asset"
|
|
3555
|
+
});
|
|
3556
|
+
return { asset: getAddress(asset), wei: assets };
|
|
3557
|
+
} catch {
|
|
3558
|
+
return null;
|
|
3559
|
+
}
|
|
3560
|
+
}
|
|
3561
|
+
async function readBorrowDebtWei(client, borrowVault, subAccount) {
|
|
3562
|
+
try {
|
|
3563
|
+
const debt = await client.readContract({
|
|
3564
|
+
address: borrowVault,
|
|
3565
|
+
abi: debtOfAbi2,
|
|
3566
|
+
functionName: "debtOf",
|
|
3567
|
+
args: [subAccount]
|
|
3568
|
+
});
|
|
3569
|
+
if (debt === 0n) return null;
|
|
3570
|
+
const asset = await client.readContract({
|
|
3571
|
+
address: borrowVault,
|
|
3572
|
+
abi: vaultSupplyAbi2,
|
|
3573
|
+
functionName: "asset"
|
|
3574
|
+
});
|
|
3575
|
+
return { asset: getAddress(asset), wei: debt };
|
|
3576
|
+
} catch {
|
|
3577
|
+
return null;
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
function mergeWei(into, asset, wei) {
|
|
3581
|
+
const k = asset.toLowerCase();
|
|
3582
|
+
into.set(k, (into.get(k) ?? 0n) + wei);
|
|
3583
|
+
}
|
|
3584
|
+
async function fetchCoingeckoContractUsdFromDetail(args) {
|
|
3585
|
+
const a = args.contractAddressLower.trim().toLowerCase();
|
|
3586
|
+
if (!a.startsWith("0x")) return null;
|
|
3587
|
+
const url = `https://api.coingecko.com/api/v3/coins/${encodeURIComponent(args.platform)}/contract/${a}`;
|
|
3588
|
+
try {
|
|
3589
|
+
const r = await fetch(url, { cache: "no-store" });
|
|
3590
|
+
if (!r.ok) return null;
|
|
3591
|
+
const j = await r.json();
|
|
3592
|
+
const u = j.market_data?.current_price?.usd;
|
|
3593
|
+
if (typeof u !== "number" || !Number.isFinite(u) || u < 0) return null;
|
|
3594
|
+
return u;
|
|
3595
|
+
} catch {
|
|
3596
|
+
return null;
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
async function augmentMissingTokenPrices(args) {
|
|
3600
|
+
const missing = args.addressesLower.map((x) => x.trim().toLowerCase()).filter((x) => x.startsWith("0x") && !args.prices.has(x));
|
|
3601
|
+
for (const addr of missing.slice(0, 12)) {
|
|
3602
|
+
const u = await fetchCoingeckoContractUsdFromDetail({ platform: args.platform, contractAddressLower: addr });
|
|
3603
|
+
if (u != null) args.prices.set(addr, u);
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3606
|
+
var COINGECKO_CHUNK = 45;
|
|
3607
|
+
async function fetchCoingeckoTokenUsdByContract(args) {
|
|
3608
|
+
const platform = COINGECKO_PLATFORM_BY_CHAIN_ID[String(args.chainId)];
|
|
3609
|
+
const out = /* @__PURE__ */ new Map();
|
|
3610
|
+
if (!platform || args.contractAddressesLower.length === 0) return out;
|
|
3611
|
+
const uniq = [...new Set(args.contractAddressesLower.map((a) => a.trim().toLowerCase()).filter((a) => a.startsWith("0x")))];
|
|
3612
|
+
for (let i = 0; i < uniq.length; i += COINGECKO_CHUNK) {
|
|
3613
|
+
const chunk = uniq.slice(i, i + COINGECKO_CHUNK);
|
|
3614
|
+
const url = `https://api.coingecko.com/api/v3/simple/token_price/${encodeURIComponent(platform)}?contract_addresses=${chunk.join(",")}&vs_currencies=usd`;
|
|
3615
|
+
try {
|
|
3616
|
+
const proxy = getCoingeckoProxyUrl();
|
|
3617
|
+
const r = proxy ? await fetch(proxy, {
|
|
3618
|
+
method: "POST",
|
|
3619
|
+
headers: { "content-type": "application/json" },
|
|
3620
|
+
body: JSON.stringify({ platform, contractAddresses: chunk })
|
|
3621
|
+
}) : await fetch(url, { cache: "no-store" });
|
|
3622
|
+
if (!r.ok) continue;
|
|
3623
|
+
const j = await r.json();
|
|
3624
|
+
for (const [addr, row] of Object.entries(j)) {
|
|
3625
|
+
const u = row?.usd;
|
|
3626
|
+
if (typeof u === "number" && Number.isFinite(u) && u >= 0) out.set(addr.toLowerCase(), u);
|
|
3627
|
+
}
|
|
3628
|
+
} catch {
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
return out;
|
|
3632
|
+
}
|
|
3633
|
+
function sumSideUsd(args) {
|
|
3634
|
+
let partial = false;
|
|
3635
|
+
let total = 0;
|
|
3636
|
+
let anyPriced = false;
|
|
3637
|
+
let anyUnpricedNonZero = false;
|
|
3638
|
+
const entries = [...args.byAssetWei.entries()].filter(([, w]) => w > 0n);
|
|
3639
|
+
if (entries.length === 0) return { usd: 0, partial: false };
|
|
3640
|
+
for (const [assetLow, wei] of entries) {
|
|
3641
|
+
const dec = args.decimalsByAsset.get(assetLow) ?? 18;
|
|
3642
|
+
const p = args.prices.get(assetLow);
|
|
3643
|
+
if (p == null) {
|
|
3644
|
+
partial = true;
|
|
3645
|
+
anyUnpricedNonZero = true;
|
|
3646
|
+
continue;
|
|
3647
|
+
}
|
|
3648
|
+
let humanAmt;
|
|
3649
|
+
try {
|
|
3650
|
+
humanAmt = Number.parseFloat(formatUnits(wei, dec));
|
|
3651
|
+
} catch {
|
|
3652
|
+
partial = true;
|
|
3653
|
+
anyUnpricedNonZero = true;
|
|
3654
|
+
continue;
|
|
3655
|
+
}
|
|
3656
|
+
const slice = humanAmt * p;
|
|
3657
|
+
if (!Number.isFinite(humanAmt) || !Number.isFinite(p) || !Number.isFinite(slice)) {
|
|
3658
|
+
partial = true;
|
|
3659
|
+
anyUnpricedNonZero = true;
|
|
3660
|
+
continue;
|
|
3661
|
+
}
|
|
3662
|
+
anyPriced = true;
|
|
3663
|
+
total += slice;
|
|
3664
|
+
}
|
|
3665
|
+
if (anyUnpricedNonZero && !anyPriced) return { usd: null, partial: true };
|
|
3666
|
+
if (anyUnpricedNonZero) partial = true;
|
|
3667
|
+
if (!Number.isFinite(total)) return { usd: null, partial: true };
|
|
3668
|
+
return { usd: total, partial };
|
|
3669
|
+
}
|
|
3670
|
+
async function loadEulerV2PortfolioUsdSnapshot(args) {
|
|
3671
|
+
const rpc = args.rpcUrl.trim();
|
|
3672
|
+
const empty = {
|
|
3673
|
+
totalSuppliedUsd: null,
|
|
3674
|
+
totalBorrowedUsd: null,
|
|
3675
|
+
netAssetValueUsd: null,
|
|
3676
|
+
partialPricing: false,
|
|
3677
|
+
pricingUnavailable: false,
|
|
3678
|
+
error: null
|
|
3679
|
+
};
|
|
3680
|
+
if (!rpc) {
|
|
3681
|
+
return { ...empty, error: "No RPC URL." };
|
|
3682
|
+
}
|
|
3683
|
+
const platform = COINGECKO_PLATFORM_BY_CHAIN_ID[String(args.chainId)];
|
|
3684
|
+
try {
|
|
3685
|
+
const mainLower = args.mainAddress.toLowerCase();
|
|
3686
|
+
const { deposits, borrows } = await gqlTrackingAccount(args.chainId, mainLower);
|
|
3687
|
+
const client = publicClient(args.chainId, rpc);
|
|
3688
|
+
const suppliedWeiByAsset = /* @__PURE__ */ new Map();
|
|
3689
|
+
const borrowedWeiByAsset = /* @__PURE__ */ new Map();
|
|
3690
|
+
const borrowPairSeen = /* @__PURE__ */ new Set();
|
|
3691
|
+
const borrowPairs = [];
|
|
3692
|
+
const pushBorrowPair = (sub, vault) => {
|
|
3693
|
+
const k = `${sub.toLowerCase()}-${vault.toLowerCase()}`;
|
|
3694
|
+
if (borrowPairSeen.has(k)) return;
|
|
3695
|
+
borrowPairSeen.add(k);
|
|
3696
|
+
borrowPairs.push({ subAccount: sub, vault });
|
|
3697
|
+
};
|
|
3698
|
+
const supplyReads = [];
|
|
3699
|
+
for (const entry of deposits) {
|
|
3700
|
+
const p = parseEulerTrackingBorrowEntry(entry);
|
|
3701
|
+
if (!p) continue;
|
|
3702
|
+
pushBorrowPair(p.subAccount, p.borrowVault);
|
|
3703
|
+
supplyReads.push(
|
|
3704
|
+
(async () => {
|
|
3705
|
+
const r = await readSupplyUnderlyingWei2(client, p.borrowVault, p.subAccount);
|
|
3706
|
+
if (!r) return;
|
|
3707
|
+
mergeWei(suppliedWeiByAsset, r.asset, r.wei);
|
|
3708
|
+
})()
|
|
3709
|
+
);
|
|
3710
|
+
}
|
|
3711
|
+
for (const entry of borrows) {
|
|
3712
|
+
const p = parseEulerTrackingBorrowEntry(entry);
|
|
3713
|
+
if (!p) continue;
|
|
3714
|
+
pushBorrowPair(p.subAccount, p.borrowVault);
|
|
3715
|
+
}
|
|
3716
|
+
const borrowReads = borrowPairs.map(
|
|
3717
|
+
({ subAccount, vault }) => (async () => {
|
|
3718
|
+
const r = await readBorrowDebtWei(client, vault, subAccount);
|
|
3719
|
+
if (!r) return;
|
|
3720
|
+
mergeWei(borrowedWeiByAsset, r.asset, r.wei);
|
|
3721
|
+
})()
|
|
3722
|
+
);
|
|
3723
|
+
await Promise.all([...supplyReads, ...borrowReads]);
|
|
3724
|
+
const allAssets = /* @__PURE__ */ new Set();
|
|
3725
|
+
for (const [a, w] of suppliedWeiByAsset) if (w > 0n) allAssets.add(a.toLowerCase());
|
|
3726
|
+
for (const [a, w] of borrowedWeiByAsset) if (w > 0n) allAssets.add(a.toLowerCase());
|
|
3727
|
+
const decimalsByAsset = /* @__PURE__ */ new Map();
|
|
3728
|
+
for (const low of allAssets) {
|
|
3729
|
+
if (!isAddress(low)) continue;
|
|
3730
|
+
const dec = await decimalsForAsset(client, getAddress(low));
|
|
3731
|
+
decimalsByAsset.set(low.toLowerCase(), dec);
|
|
3732
|
+
}
|
|
3733
|
+
const prices = platform != null ? await fetchCoingeckoTokenUsdByContract({
|
|
3734
|
+
chainId: args.chainId,
|
|
3735
|
+
contractAddressesLower: [...allAssets]
|
|
3736
|
+
}) : /* @__PURE__ */ new Map();
|
|
3737
|
+
if (platform != null && allAssets.size > 0) {
|
|
3738
|
+
await augmentMissingTokenPrices({
|
|
3739
|
+
platform,
|
|
3740
|
+
addressesLower: [...allAssets],
|
|
3741
|
+
prices
|
|
3742
|
+
});
|
|
3743
|
+
}
|
|
3744
|
+
const s = sumSideUsd({ byAssetWei: suppliedWeiByAsset, decimalsByAsset, prices });
|
|
3745
|
+
const b = sumSideUsd({ byAssetWei: borrowedWeiByAsset, decimalsByAsset, prices });
|
|
3746
|
+
const sUsd = s.usd != null && Number.isFinite(s.usd) ? s.usd : null;
|
|
3747
|
+
const bUsd = b.usd != null && Number.isFinite(b.usd) ? b.usd : null;
|
|
3748
|
+
let nav = null;
|
|
3749
|
+
if (sUsd != null && bUsd != null) nav = sUsd - bUsd;
|
|
3750
|
+
else if (sUsd != null && (borrowedWeiByAsset.size === 0 || [...borrowedWeiByAsset.values()].every((w) => w === 0n))) {
|
|
3751
|
+
nav = sUsd;
|
|
3752
|
+
} else if (bUsd != null && (suppliedWeiByAsset.size === 0 || [...suppliedWeiByAsset.values()].every((w) => w === 0n))) {
|
|
3753
|
+
nav = -bUsd;
|
|
3754
|
+
}
|
|
3755
|
+
if (nav != null && !Number.isFinite(nav)) nav = null;
|
|
3756
|
+
const hasAnyPosition = [...suppliedWeiByAsset.values(), ...borrowedWeiByAsset.values()].some((w) => w > 0n);
|
|
3757
|
+
const partialPricing = s.partial || b.partial;
|
|
3758
|
+
const pricingUnavailable = platform == null && hasAnyPosition;
|
|
3759
|
+
return {
|
|
3760
|
+
totalSuppliedUsd: sUsd,
|
|
3761
|
+
totalBorrowedUsd: bUsd,
|
|
3762
|
+
netAssetValueUsd: nav,
|
|
3763
|
+
partialPricing: platform != null && partialPricing,
|
|
3764
|
+
pricingUnavailable,
|
|
3765
|
+
error: null
|
|
3766
|
+
};
|
|
3767
|
+
} catch (e) {
|
|
3768
|
+
return {
|
|
3769
|
+
...empty,
|
|
3770
|
+
error: e instanceof Error ? e.message : "Could not load portfolio."
|
|
3771
|
+
};
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3775
|
+
// src/protocols/evm/euler-v2/loadEulerV2SupportedChainIds.ts
|
|
3776
|
+
var cached = null;
|
|
3777
|
+
function loadEulerV2SupportedChainIds() {
|
|
3778
|
+
if (cached) return Promise.resolve(cached);
|
|
3779
|
+
cached = new Set(Object.keys(EULER_V2_GOLDSKY_SUBGRAPH_URL_BY_CHAIN_ID).map((k) => Number(k)));
|
|
3780
|
+
return Promise.resolve(cached);
|
|
3781
|
+
}
|
|
3782
|
+
|
|
1536
3783
|
// src/protocols/evm/euler-v2/index.ts
|
|
1537
3784
|
var EULER_V2_PROTOCOL_ID = "euler-v2";
|
|
1538
3785
|
var eulerV2ProtocolModule = {
|
|
@@ -1555,6 +3802,6 @@ var eulerV2ProtocolModule = {
|
|
|
1555
3802
|
};
|
|
1556
3803
|
registerProtocolModule(eulerV2ProtocolModule);
|
|
1557
3804
|
|
|
1558
|
-
export { EULER_SAME_ASSET_BORROW_APPROVAL_BUFFER_BPS, EULER_SAME_ASSET_BORROW_MAX_ROUNDS, EULER_SAME_ASSET_BORROW_PROTOCOL_HEADROOM_BPS, EULER_SAME_ASSET_BORROW_RATIO_STOP_EPS_BPS, EULER_V2_ISOLATED_VAULT_DEPOSIT_FALLBACK_GAS, EULER_V2_PROTOCOL_ID, EULER_V2_VAULT_WITHDRAW_FALLBACK_GAS, buildEvmMultisignBodyEulerV2BorrowCollateralDepositBatch, buildEvmMultisignBodyEulerV2BorrowCollateralWithdrawBatch, buildEvmMultisignBodyEulerV2BorrowRepayBatch, buildEvmMultisignBodyEulerV2IsolatedBorrowBatch, buildEvmMultisignBodyEulerV2IsolatedLendDepositBatch, buildEvmMultisignBodyEulerV2VaultWithdraw, clampEulerUnderlyingDecimalsForEulerUi, eulerBorrowAndCollateralSameAsset, eulerSameAssetApproveAmountWithBuffer, eulerSameAssetTotalCollateralPullWei, eulerV2ProtocolModule, fetchEulerBorrowCollateralMaxWithdrawAssetsWei, fetchEulerLendEarnVaultEffectiveMaxWithdrawWei, fetchEulerVaultAssetDecimals, fetchEulerVaultMaxWithdrawWei, fetchEulerVaultUnderlyingMeta, planSameAssetLeveragedBorrows };
|
|
3805
|
+
export { EULER_EVAULT_CAP_UNLIMITED_WEI, EULER_EVAULT_SUPPLY_CAP_UNLIMITED_WEI, EULER_REUL_UNLOCK_GAS_FALLBACK, EULER_SAME_ASSET_BORROW_APPROVAL_BUFFER_BPS, EULER_SAME_ASSET_BORROW_MAX_ROUNDS, EULER_SAME_ASSET_BORROW_PROTOCOL_HEADROOM_BPS, EULER_SAME_ASSET_BORROW_RATIO_STOP_EPS_BPS, EULER_V2_GOLDSKY_SUBGRAPH_URL_BY_CHAIN_ID, EULER_V2_ISOLATED_VAULT_DEPOSIT_FALLBACK_GAS, EULER_V2_PREFER_ON_CHAIN_LEND_METRICS, EULER_V2_PROTOCOL_ID, EULER_V2_VAULT_WITHDRAW_FALLBACK_GAS, REUL_FULL_VEST_SEC, REUL_LOCK_DAY_SEC, buildEvmMultisignBodyEulerV2BorrowCollateralDepositBatch, buildEvmMultisignBodyEulerV2BorrowCollateralWithdrawBatch, buildEvmMultisignBodyEulerV2BorrowRepayBatch, buildEvmMultisignBodyEulerV2IsolatedBorrowBatch, buildEvmMultisignBodyEulerV2IsolatedLendDepositBatch, buildEvmMultisignBodyEulerV2VaultWithdraw, clampEulerUnderlyingDecimalsForEulerUi, encodeEulerReulWithdrawToByLockTimestampsData, ensureEulerV2ChainAssetCache, estimateBorrowHumanFromLtv, eulerBorrowAndCollateralSameAsset, eulerLabelsAppendUnderlyingIfDistinct, eulerLabelsLookupLabelForVault, eulerReulUnlockAbi, eulerSameAssetApproveAmountWithBuffer, eulerSameAssetTotalCollateralPullWei, eulerSubgraphVaultCapToUnderlyingWei, eulerV2GoldskyUrlForChain, eulerV2KeyForNodeAssetRow, eulerV2ProtocolModule, eulerV2QueryGraphQl, eulerVaultLendMetricsFromIndexerVaultState, eulerVaultMaxNewBorrowWei, eulerVaultMaxNewSupplyWei, eulerWrappedGasTokenAliasesLower, fetchCoingeckoTokenUsdByContract, fetchEulerBorrowCollateralMaxWithdrawAssetsWei, fetchEulerLabelsEarnVaultAllowlist, fetchEulerLabelsEntityNameByAddress, fetchEulerLabelsVaultNameMap, fetchEulerLendEarnVaultEffectiveMaxWithdrawWei, fetchEulerReulVestingTranches, fetchEulerV2BorrowDebtWei, fetchEulerV2BorrowOracleQuoteSnapshot, fetchEulerV2BorrowPairLtvs, fetchEulerV2ChainAssetCache, fetchEulerV2EarnOfferingsForRowAsset, fetchEulerV2IsolatedLendMarketsForRowAsset, fetchEulerV2TrackingBorrowEntries, fetchEulerV2TrackingDepositEntries, fetchEulerVaultAssetDecimals, fetchEulerVaultMaxWithdrawWei, fetchEulerVaultOnChainLendMetrics, fetchEulerVaultOnChainLendMetricsForVaults, fetchEulerVaultUnderlyingMeta, flattenEulerV2BorrowCollateralRows, formatEulerRayApyPercent, formatEulerRaySupplyApyPercent, formatEulerResolvedCapOrCashForUi, loadEulerV2BorrowPositionsForOwner, loadEulerV2LendSupplyPositionsForOwner, loadEulerV2PortfolioUsdSnapshot, loadEulerV2SupportedChainIds, maxCollateralWeiCappedByBorrowLiquidity, mergeEulerV2PositionsTabRows, parseEulerTrackingBorrowEntry, planSameAssetLeveragedBorrows, resolveEulerAmountCapToSupplyWei, resolveEulerAmountCapToWei, resolveEulerWrappedNativeToken };
|
|
1559
3806
|
//# sourceMappingURL=index.js.map
|
|
1560
3807
|
//# sourceMappingURL=index.js.map
|