@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.
Files changed (57) hide show
  1. package/dist/agent/catalog.cjs +62 -11
  2. package/dist/agent/catalog.cjs.map +1 -1
  3. package/dist/agent/catalog.d.ts +27 -1
  4. package/dist/agent/catalog.js +61 -12
  5. package/dist/agent/catalog.js.map +1 -1
  6. package/dist/agent/skills/curve-dao/SKILL.md +2 -1
  7. package/dist/chains/evm/index.cjs +54 -0
  8. package/dist/chains/evm/index.cjs.map +1 -1
  9. package/dist/chains/evm/index.d.ts +13 -1
  10. package/dist/chains/evm/index.js +52 -2
  11. package/dist/chains/evm/index.js.map +1 -1
  12. package/dist/core/index.cjs +64 -0
  13. package/dist/core/index.cjs.map +1 -1
  14. package/dist/core/index.d.ts +20 -1
  15. package/dist/core/index.js +56 -1
  16. package/dist/core/index.js.map +1 -1
  17. package/dist/index.cjs +131 -0
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.js +120 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/protocols/evm/aave-v4/index.cjs +766 -6
  23. package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
  24. package/dist/protocols/evm/aave-v4/index.d.ts +417 -1
  25. package/dist/protocols/evm/aave-v4/index.js +741 -8
  26. package/dist/protocols/evm/aave-v4/index.js.map +1 -1
  27. package/dist/protocols/evm/curve-dao/index.cjs +233 -7
  28. package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
  29. package/dist/protocols/evm/curve-dao/index.d.ts +66 -1
  30. package/dist/protocols/evm/curve-dao/index.js +227 -9
  31. package/dist/protocols/evm/curve-dao/index.js.map +1 -1
  32. package/dist/protocols/evm/ethena/index.cjs +104 -0
  33. package/dist/protocols/evm/ethena/index.cjs.map +1 -1
  34. package/dist/protocols/evm/ethena/index.d.ts +46 -1
  35. package/dist/protocols/evm/ethena/index.js +99 -1
  36. package/dist/protocols/evm/ethena/index.js.map +1 -1
  37. package/dist/protocols/evm/euler-v2/index.cjs +2334 -37
  38. package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
  39. package/dist/protocols/evm/euler-v2/index.d.ts +464 -1
  40. package/dist/protocols/evm/euler-v2/index.js +2286 -39
  41. package/dist/protocols/evm/euler-v2/index.js.map +1 -1
  42. package/dist/protocols/evm/lido/index.cjs +110 -0
  43. package/dist/protocols/evm/lido/index.cjs.map +1 -1
  44. package/dist/protocols/evm/lido/index.d.ts +33 -2
  45. package/dist/protocols/evm/lido/index.js +107 -2
  46. package/dist/protocols/evm/lido/index.js.map +1 -1
  47. package/dist/protocols/evm/maple/index.cjs +83 -0
  48. package/dist/protocols/evm/maple/index.cjs.map +1 -1
  49. package/dist/protocols/evm/maple/index.d.ts +22 -1
  50. package/dist/protocols/evm/maple/index.js +82 -1
  51. package/dist/protocols/evm/maple/index.js.map +1 -1
  52. package/dist/protocols/evm/sky/index.cjs +217 -0
  53. package/dist/protocols/evm/sky/index.cjs.map +1 -1
  54. package/dist/protocols/evm/sky/index.d.ts +56 -1
  55. package/dist/protocols/evm/sky/index.js +210 -2
  56. package/dist/protocols/evm/sky/index.js.map +1 -1
  57. 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 publicClient = createPublicClient({ chain: ch, transport: http(rpcUrl) });
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 publicClient.getBlock({ blockTag: "latest" })).baseFeePerGas ?? 0n : 0n;
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 publicClient.getTransactionCount({ address: executor, blockTag: "pending" });
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 publicClient.estimateGas({
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 publicClient.getGasPrice();
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
335
- const assetAddrRaw = await publicClient.readContract({
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 publicClient.readContract({
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
374
- return publicClient.readContract({
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
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
- publicClient.readContract({
417
+ publicClient2.readContract({
418
418
  address: args.evault,
419
419
  abi: eulerVaultSharesCashAbi,
420
420
  functionName: "balanceOf",
421
421
  args: [args.vaultShareOwner]
422
422
  }),
423
- publicClient.readContract({
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 publicClient.readContract({
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
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
- publicClient.readContract({
622
+ publicClient2.readContract({
623
623
  address: args.collateralVault,
624
624
  abi: eulerCollateralVaultReadAbi,
625
625
  functionName: "balanceOf",
626
626
  args: [args.subAccount]
627
627
  }),
628
- publicClient.readContract({
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 publicClient.readContract({
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
724
- const dec = await publicClient.readContract({
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 publicClient.readContract({
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 publicClient.readContract({
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
919
- const cDecRaw = await publicClient.readContract({
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 publicClient.readContract({
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 publicClient.readContract({
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 publicClient.readContract({
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
1171
- const bDecRaw = await publicClient.readContract({
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 publicClient.readContract({
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 publicClient.readContract({
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 publicClient = createPublicClient({ chain: ch, transport: http(args.rpcUrl) });
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 publicClient.readContract({
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