@continuumdao/ctm-mpc-defi 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/catalog.cjs +62 -11
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +27 -1
- package/dist/agent/catalog.js +61 -12
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/curve-dao/SKILL.md +2 -1
- package/dist/chains/evm/index.cjs +54 -0
- package/dist/chains/evm/index.cjs.map +1 -1
- package/dist/chains/evm/index.d.ts +13 -1
- package/dist/chains/evm/index.js +52 -2
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/core/index.cjs +64 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.ts +20 -1
- package/dist/core/index.js +56 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +131 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +120 -2
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs +766 -6
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/aave-v4/index.d.ts +417 -1
- package/dist/protocols/evm/aave-v4/index.js +741 -8
- package/dist/protocols/evm/aave-v4/index.js.map +1 -1
- package/dist/protocols/evm/curve-dao/index.cjs +233 -7
- package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/curve-dao/index.d.ts +66 -1
- package/dist/protocols/evm/curve-dao/index.js +227 -9
- package/dist/protocols/evm/curve-dao/index.js.map +1 -1
- package/dist/protocols/evm/ethena/index.cjs +104 -0
- package/dist/protocols/evm/ethena/index.cjs.map +1 -1
- package/dist/protocols/evm/ethena/index.d.ts +46 -1
- package/dist/protocols/evm/ethena/index.js +99 -1
- package/dist/protocols/evm/ethena/index.js.map +1 -1
- package/dist/protocols/evm/euler-v2/index.cjs +2334 -37
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
- package/dist/protocols/evm/euler-v2/index.d.ts +464 -1
- package/dist/protocols/evm/euler-v2/index.js +2286 -39
- package/dist/protocols/evm/euler-v2/index.js.map +1 -1
- package/dist/protocols/evm/lido/index.cjs +110 -0
- package/dist/protocols/evm/lido/index.cjs.map +1 -1
- package/dist/protocols/evm/lido/index.d.ts +33 -2
- package/dist/protocols/evm/lido/index.js +107 -2
- package/dist/protocols/evm/lido/index.js.map +1 -1
- package/dist/protocols/evm/maple/index.cjs +83 -0
- package/dist/protocols/evm/maple/index.cjs.map +1 -1
- package/dist/protocols/evm/maple/index.d.ts +22 -1
- package/dist/protocols/evm/maple/index.js +82 -1
- package/dist/protocols/evm/maple/index.js.map +1 -1
- package/dist/protocols/evm/sky/index.cjs +217 -0
- package/dist/protocols/evm/sky/index.cjs.map +1 -1
- package/dist/protocols/evm/sky/index.d.ts +56 -1
- package/dist/protocols/evm/sky/index.js +210 -2
- package/dist/protocols/evm/sky/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
337
|
-
const assetAddrRaw = await
|
|
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
|
|
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
|
|
376
|
-
return
|
|
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
|
|
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
|
-
|
|
419
|
+
publicClient2.readContract({
|
|
420
420
|
address: args.evault,
|
|
421
421
|
abi: eulerVaultSharesCashAbi,
|
|
422
422
|
functionName: "balanceOf",
|
|
423
423
|
args: [args.vaultShareOwner]
|
|
424
424
|
}),
|
|
425
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
624
|
+
publicClient2.readContract({
|
|
625
625
|
address: args.collateralVault,
|
|
626
626
|
abi: eulerCollateralVaultReadAbi,
|
|
627
627
|
functionName: "balanceOf",
|
|
628
628
|
args: [args.subAccount]
|
|
629
629
|
}),
|
|
630
|
-
|
|
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
|
|
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
|
|
726
|
-
const dec = await
|
|
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
|
|
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
|
|
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
|
|
921
|
-
const cDecRaw = await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1173
|
-
const bDecRaw = await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|