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