From 06769f3fe41ed08a90c62c77550f7a730fdb08ad Mon Sep 17 00:00:00 2001 From: rossgalloway <58150151+rossgalloway@users.noreply.github.com> Date: Mon, 25 May 2026 20:31:32 +0000 Subject: [PATCH 1/3] update to use kong and public RPCs --- .env.example | 1 + README.md | 4 +- docusaurus.config.js | 7 ++- src/components/veYFI-calculator/fetch.ts | 47 ++++++++++++++++--- .../veYFI-calculator/veYFI-calculator.tsx | 14 ++---- src/ethereum/publicRpc.ts | 6 --- 6 files changed, 53 insertions(+), 26 deletions(-) diff --git a/.env.example b/.env.example index 01c757b18..d9c984f16 100644 --- a/.env.example +++ b/.env.example @@ -6,3 +6,4 @@ VITE_RPC_URI_FOR_250=https://rpc.yearn.fi/chain/250 VITE_RPC_URI_FOR_8453=https://rpc.yearn.fi/chain/8453 VITE_RPC_URI_FOR_42161=https://rpc.yearn.fi/chain/42161 VITE_RPC_URI_FOR_747474=https://rpc.yearn.fi/chain/747474 +KONG_ENDPOINT=https://kong.yearn.fi/api/rest diff --git a/README.md b/README.md index d58d4ff1e..f22902441 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,9 @@ By default, the repo will use Yearn RPC endpoints in the form `https://rpc.yearn Runtime docs reads use the chain declared in each page's `rpcCalls` frontmatter. The address-check script is still mainnet-only today, so it uses chain `1`. -The legacy `ALCHEMY_API_KEY` mainnet fallback is still supported temporarily for compatibility, but `VITE_RPC_URI_FOR_1` is now the preferred configuration. +The site reads vault snapshots from Kong. Set `KONG_ENDPOINT` only when you need to point at a different Kong-compatible REST host. + +`ALCHEMY_API_KEY` is no longer read by the site. Use `VITE_RPC_URI_FOR_1` or `RPC_URI_FOR_1` for mainnet RPC overrides. ## Deployment diff --git a/docusaurus.config.js b/docusaurus.config.js index 79ed809e2..00becbbbd 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -9,8 +9,8 @@ import { getRpcUriOverridesFromEnv } from './src/ethereum/publicRpc' const branchName = process.env.BRANCH_NAME || 'unknown' const isDev = process.env.IS_DEV === 'true' const rpcUris = getRpcUriOverridesFromEnv(process.env) -const yDaemon = process.env.YDAEMON_ENDPOINT || 'unknown' -const yPriceMagic = process.env.YPRICEMAGIC_ENDPOINT || 'unknown' +const kongEndpoint = + process.env.KONG_ENDPOINT || 'https://kong.yearn.fi/api/rest' export default { title: 'Yearn Docs', @@ -31,8 +31,7 @@ export default { branchName, isDev, rpcUris, - yDaemon, - yPriceMagic, + kongEndpoint, }, future: { experimental_faster: true, diff --git a/src/components/veYFI-calculator/fetch.ts b/src/components/veYFI-calculator/fetch.ts index 3ff634553..f3b82af7d 100644 --- a/src/components/veYFI-calculator/fetch.ts +++ b/src/components/veYFI-calculator/fetch.ts @@ -82,12 +82,47 @@ export async function fetchAllGaugeData(publicClient: any) { return Promise.all(gaugeDataPromises) } -export async function fetchTokenPrice(yDaemon: string, address: string) { - const response = await fetch(`${yDaemon}/1/vaults/${address}`) +type KongVaultSnapshot = { + decimals?: number | string + pricePerShare?: string + totalAssets?: string + tvl?: { + close?: number + } + asset?: { + decimals?: number | string + } +} + +const formatScaledAmount = ( + value: string | undefined, + decimals: number | string | undefined +) => { + if (!value || decimals === undefined) { + return 0 + } + + return Number(formatUnits(BigInt(value), Number(decimals))) +} + +export async function fetchVaultSharePrice( + kongEndpoint: string, + address: string +) { + const response = await fetch(`${kongEndpoint}/snapshot/1/${address}`) if (!response.ok) { - console.error('Failed to fetch token price') - return null + console.error('Failed to fetch vault snapshot') + return undefined } - const data = await response.json() - return data + + const data = (await response.json()) as KongVaultSnapshot + const totalAssets = formatScaledAmount( + data.totalAssets, + data.asset?.decimals + ) + const assetPrice = + data.tvl?.close && totalAssets > 0 ? data.tvl.close / totalAssets : 0 + const pricePerShare = formatScaledAmount(data.pricePerShare, data.decimals) + + return pricePerShare * assetPrice } diff --git a/src/components/veYFI-calculator/veYFI-calculator.tsx b/src/components/veYFI-calculator/veYFI-calculator.tsx index ed34ed664..5b41473d0 100644 --- a/src/components/veYFI-calculator/veYFI-calculator.tsx +++ b/src/components/veYFI-calculator/veYFI-calculator.tsx @@ -33,7 +33,7 @@ import { import { fetchVeYFISupply, fetchAllGaugeData, - fetchTokenPrice, + fetchVaultSharePrice, fetchLiquidLockerVeYFIBalance, } from './fetch' import BoostChart from './BoostChart' @@ -60,9 +60,8 @@ const VeYFICalculator: React.FC = () => { const { getPublicClient } = useContext(PublicClientContext) const publicClient = getPublicClient(DEFAULT_MAINNET_CHAIN_ID) const { siteConfig } = useDocusaurusContext() - const { yDaemon } = siteConfig.customFields as { - yDaemon: string - yPriceMagic: string + const { kongEndpoint } = siteConfig.customFields as { + kongEndpoint: string } const [veYfiTotalSupply, setVeYfiTotalSupply] = useState(0) @@ -189,13 +188,10 @@ const VeYFICalculator: React.FC = () => { setSelectedVault(vaultName) const selectedGauge = gaugeData.find((gauge) => gauge.name === vaultName) if (selectedGauge) { - const tokenPriceData = await fetchTokenPrice( - yDaemon, + const vaultSharePrice = await fetchVaultSharePrice( + kongEndpoint, selectedGauge.underlyingVaultAddress ) - const underlyingPrice = tokenPriceData?.tvl.price - const pricePerShare = tokenPriceData?.apr.pricePerShare.today - const vaultSharePrice = pricePerShare * underlyingPrice setSelectedVaultSharePrice(vaultSharePrice) } setShowChart1(false) diff --git a/src/ethereum/publicRpc.ts b/src/ethereum/publicRpc.ts index d696f22a2..68b27c538 100644 --- a/src/ethereum/publicRpc.ts +++ b/src/ethereum/publicRpc.ts @@ -72,12 +72,6 @@ export function getRpcUriOverridesFromEnv( } } - const legacyAlchemyKey = env.ALCHEMY_API_KEY?.trim() - if (legacyAlchemyKey && !rpcUris[String(DEFAULT_MAINNET_CHAIN_ID)]) { - rpcUris[String(DEFAULT_MAINNET_CHAIN_ID)] = - `https://eth-mainnet.g.alchemy.com/v2/${legacyAlchemyKey}` - } - return rpcUris } From ec50505742ee0425cbefefeb5bbc8e6d9272b511 Mon Sep 17 00:00:00 2001 From: rossgalloway <58150151+rossgalloway@users.noreply.github.com> Date: Tue, 26 May 2026 13:12:40 +0000 Subject: [PATCH 2/3] fix copilot review --- src/components/veYFI-calculator/fetch.ts | 50 +++++++++++++------ .../veYFI-calculator/veYFI-calculator.tsx | 50 ++++++++++++++----- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/src/components/veYFI-calculator/fetch.ts b/src/components/veYFI-calculator/fetch.ts index f3b82af7d..78aaec3a9 100644 --- a/src/components/veYFI-calculator/fetch.ts +++ b/src/components/veYFI-calculator/fetch.ts @@ -99,30 +99,48 @@ const formatScaledAmount = ( decimals: number | string | undefined ) => { if (!value || decimals === undefined) { - return 0 + return undefined } - return Number(formatUnits(BigInt(value), Number(decimals))) + const amount = Number(formatUnits(BigInt(value), Number(decimals))) + return Number.isFinite(amount) ? amount : undefined } export async function fetchVaultSharePrice( kongEndpoint: string, address: string ) { - const response = await fetch(`${kongEndpoint}/snapshot/1/${address}`) - if (!response.ok) { - console.error('Failed to fetch vault snapshot') - return undefined - } + try { + const endpoint = kongEndpoint.replace(/\/+$/, '') + const response = await fetch(`${endpoint}/snapshot/1/${address}`) + if (!response.ok) { + console.error('Failed to fetch vault snapshot') + return undefined + } - const data = (await response.json()) as KongVaultSnapshot - const totalAssets = formatScaledAmount( - data.totalAssets, - data.asset?.decimals - ) - const assetPrice = - data.tvl?.close && totalAssets > 0 ? data.tvl.close / totalAssets : 0 - const pricePerShare = formatScaledAmount(data.pricePerShare, data.decimals) + const data = (await response.json()) as KongVaultSnapshot + const totalAssets = formatScaledAmount( + data.totalAssets, + data.asset?.decimals + ) + const tvl = data.tvl?.close + const pricePerShare = formatScaledAmount(data.pricePerShare, data.decimals) + + if ( + !totalAssets || + !tvl || + !pricePerShare || + totalAssets <= 0 || + tvl <= 0 || + pricePerShare <= 0 + ) { + return undefined + } - return pricePerShare * assetPrice + const sharePrice = pricePerShare * (tvl / totalAssets) + return Number.isFinite(sharePrice) ? sharePrice : undefined + } catch (error) { + console.error('Failed to fetch vault snapshot', error) + return undefined + } } diff --git a/src/components/veYFI-calculator/veYFI-calculator.tsx b/src/components/veYFI-calculator/veYFI-calculator.tsx index 5b41473d0..9ef1a9f84 100644 --- a/src/components/veYFI-calculator/veYFI-calculator.tsx +++ b/src/components/veYFI-calculator/veYFI-calculator.tsx @@ -72,6 +72,9 @@ const VeYFICalculator: React.FC = () => { const [selectedVaultSharePrice, setSelectedVaultSharePrice] = useState< number | undefined >(undefined) + const [vaultPriceError, setVaultPriceError] = useState( + undefined + ) const [depositAmount, setDepositAmount] = useState('') const [depositAmountInUSD, setDepositAmountInUSD] = useState( '' @@ -98,6 +101,10 @@ const VeYFICalculator: React.FC = () => { >({}) const [useLiquidLocker, setUseLiquidLocker] = useState(false) const [isDataFetched, setIsDataFetched] = useState(false) + const hasValidVaultSharePrice = + selectedVaultSharePrice !== undefined && + Number.isFinite(selectedVaultSharePrice) && + selectedVaultSharePrice > 0 useEffect(() => { const fetchData = async () => { @@ -138,11 +145,10 @@ const VeYFICalculator: React.FC = () => { return } if (!isNaN(Number(val))) { - const depositAmountInDollars = selectedVaultSharePrice - ? selectedVaultSharePrice * Number(val) - : 0 - setDepositAmountInUSD(depositAmountInDollars) setDepositAmount(Number(val)) + setDepositAmountInUSD( + hasValidVaultSharePrice ? selectedVaultSharePrice * Number(val) : '' + ) } setShowChart1(false) setShowChart2(false) @@ -158,10 +164,9 @@ const VeYFICalculator: React.FC = () => { } if (!isNaN(Number(val))) { setDepositAmountInUSD(Number(val)) - const depositAmountInShares = selectedVaultSharePrice - ? Number(val) / selectedVaultSharePrice - : 0 - setDepositAmount(depositAmountInShares) + setDepositAmount( + hasValidVaultSharePrice ? Number(val) / selectedVaultSharePrice : '' + ) } setShowChart1(false) setShowChart2(false) @@ -186,12 +191,21 @@ const VeYFICalculator: React.FC = () => { const handleVaultChange = async (vaultName: string) => { setSelectedVault(vaultName) + setSelectedVaultSharePrice(undefined) + setVaultPriceError(undefined) const selectedGauge = gaugeData.find((gauge) => gauge.name === vaultName) if (selectedGauge) { const vaultSharePrice = await fetchVaultSharePrice( kongEndpoint, selectedGauge.underlyingVaultAddress ) + if ( + vaultSharePrice === undefined || + !Number.isFinite(vaultSharePrice) || + vaultSharePrice <= 0 + ) { + setVaultPriceError('Vault price unavailable') + } setSelectedVaultSharePrice(vaultSharePrice) } setShowChart1(false) @@ -201,6 +215,11 @@ const VeYFICalculator: React.FC = () => { } const handleCalculateButton1Click = () => { + if (!hasValidVaultSharePrice) { + setVaultPriceError('Vault price unavailable') + return + } + const vaultSharePrice = selectedVaultSharePrice const totalDeposited = gaugeData.find((g) => g.name === selectedVault)?.totalAssets || 0 const depositVal = Number(depositAmount) || 0 @@ -225,19 +244,18 @@ const VeYFICalculator: React.FC = () => { ) const dataUSD = dataShares.map((entry) => ({ ...entry, - amountDepositedInGauge: - entry.amountDepositedInGauge * (selectedVaultSharePrice ?? 0), + amountDepositedInGauge: entry.amountDepositedInGauge * vaultSharePrice, })) // get the boost for the entered deposit amount const specificBoost = calculateBoost( veYFIVal, veYfiTotalSupply, totalDeposited, - Number(depositAmountInUSD) / (selectedVaultSharePrice ?? 0) + Number(depositAmountInUSD) / vaultSharePrice ) const specificBoostDataPoint = generateSinglePoint(depositVal, calcFunc) const specificBoostDataPointUSD = - (specificBoostDataPoint?.value ?? 0) * (selectedVaultSharePrice ?? 0) + (specificBoostDataPoint?.value ?? 0) * vaultSharePrice setCalculatedBoost({ veYFI: veYFIVal, value: specificBoostDataPoint?.value || 0, @@ -251,6 +269,10 @@ const VeYFICalculator: React.FC = () => { } const handleCalculateButton2Click = () => { + if (!hasValidVaultSharePrice) { + setVaultPriceError('Vault price unavailable') + return + } const totalDeposited = gaugeData.find((g) => g.name === selectedVault)?.totalAssets || 0 const depositVal = Number(depositAmount) || 0 @@ -312,6 +334,7 @@ const VeYFICalculator: React.FC = () => { ))} + {vaultPriceError &&

{vaultPriceError}

}
{/* */} @@ -378,6 +401,7 @@ const VeYFICalculator: React.FC = () => { onClick={handleCalculateButton1Click} disabled={ !selectedVault || + !hasValidVaultSharePrice || (useVeYfiCalculator ? isNaN(Number(veYFIFromLock)) || !veYFIFromLock : isNaN(Number(veYFIAmount)) || !veYFIAmount) @@ -478,6 +502,7 @@ const VeYFICalculator: React.FC = () => { ))} + {vaultPriceError &&

{vaultPriceError}

}
{ onClick={handleCalculateButton2Click} disabled={ !selectedVault || + !hasValidVaultSharePrice || isNaN(Number(depositAmount)) || !depositAmount } From c9fdd55baa93f7bb33c7e3c52e3bbdb6c9081627 Mon Sep 17 00:00:00 2001 From: rossgalloway <58150151+rossgalloway@users.noreply.github.com> Date: Tue, 26 May 2026 14:55:39 +0000 Subject: [PATCH 3/3] remove VITE prefix --- .env.example | 16 ++++++++-------- README.md | 4 ++-- src/ethereum/publicRpc.ts | 20 +++++++++----------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/.env.example b/.env.example index d9c984f16..078addfb5 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,9 @@ -VITE_RPC_URI_FOR_1=https://rpc.yearn.fi/chain/1 -VITE_RPC_URI_FOR_10=https://rpc.yearn.fi/chain/10 -VITE_RPC_URI_FOR_100=https://rpc.yearn.fi/chain/100 -VITE_RPC_URI_FOR_137=https://rpc.yearn.fi/chain/137 -VITE_RPC_URI_FOR_250=https://rpc.yearn.fi/chain/250 -VITE_RPC_URI_FOR_8453=https://rpc.yearn.fi/chain/8453 -VITE_RPC_URI_FOR_42161=https://rpc.yearn.fi/chain/42161 -VITE_RPC_URI_FOR_747474=https://rpc.yearn.fi/chain/747474 +RPC_URI_FOR_1=https://rpc.yearn.fi/chain/1 +RPC_URI_FOR_10=https://rpc.yearn.fi/chain/10 +RPC_URI_FOR_100=https://rpc.yearn.fi/chain/100 +RPC_URI_FOR_137=https://rpc.yearn.fi/chain/137 +RPC_URI_FOR_250=https://rpc.yearn.fi/chain/250 +RPC_URI_FOR_8453=https://rpc.yearn.fi/chain/8453 +RPC_URI_FOR_42161=https://rpc.yearn.fi/chain/42161 +RPC_URI_FOR_747474=https://rpc.yearn.fi/chain/747474 KONG_ENDPOINT=https://kong.yearn.fi/api/rest diff --git a/README.md b/README.md index f22902441..f081318e9 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Artifact URLs default to `https://docs.yearn.fi`. To generate artifacts against ## Configure .env -The docs site pulls data from on-chain smart contracts and now resolves RPCs by chain. Copy `.env.example` to `.env` and set any `VITE_RPC_URI_FOR_` values you want to override. +The docs site pulls data from on-chain smart contracts and now resolves RPCs by chain. Copy `.env.example` to `.env` and set any `RPC_URI_FOR_` values you want to override. By default, the repo will use Yearn RPC endpoints in the form `https://rpc.yearn.fi/chain/`, so the example values can usually be used as-is. @@ -136,7 +136,7 @@ Runtime docs reads use the chain declared in each page's `rpcCalls` frontmatter. The site reads vault snapshots from Kong. Set `KONG_ENDPOINT` only when you need to point at a different Kong-compatible REST host. -`ALCHEMY_API_KEY` is no longer read by the site. Use `VITE_RPC_URI_FOR_1` or `RPC_URI_FOR_1` for mainnet RPC overrides. +`ALCHEMY_API_KEY` is no longer read by the site. Use `RPC_URI_FOR_1` for mainnet RPC overrides. ## Deployment diff --git a/src/ethereum/publicRpc.ts b/src/ethereum/publicRpc.ts index 68b27c538..a5d610f4c 100644 --- a/src/ethereum/publicRpc.ts +++ b/src/ethereum/publicRpc.ts @@ -3,7 +3,7 @@ import * as viemChains from 'viem/chains' const DEFAULT_RPC_BASE_URL = 'https://rpc.yearn.fi/chain' const DEFAULT_MAINNET_CHAIN_ID = 1 -const RPC_ENV_PREFIXES = ['VITE_RPC_URI_FOR_', 'RPC_URI_FOR_'] +const RPC_ENV_PREFIX = 'RPC_URI_FOR_' const knownChains = { 1: viemChains.mainnet, @@ -58,18 +58,16 @@ export function getRpcUriOverridesFromEnv( continue } - for (const prefix of RPC_ENV_PREFIXES) { - if (!key.startsWith(prefix)) { - continue - } - - const chainId = key.slice(prefix.length) - if (!/^\d+$/.test(chainId)) { - continue - } + if (!key.startsWith(RPC_ENV_PREFIX)) { + continue + } - rpcUris[chainId] = trimmedValue + const chainId = key.slice(RPC_ENV_PREFIX.length) + if (!/^\d+$/.test(chainId)) { + continue } + + rpcUris[chainId] = trimmedValue } return rpcUris