Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +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
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,15 @@ 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_<chainId>` 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_<chainId>` values you want to override.

By default, the repo will use Yearn RPC endpoints in the form `https://rpc.yearn.fi/chain/<chainId>`, so the example values can usually be used as-is.

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 `RPC_URI_FOR_1` for mainnet RPC overrides.

## Deployment

Expand Down
7 changes: 3 additions & 4 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -31,8 +31,7 @@ export default {
branchName,
isDev,
rpcUris,
yDaemon,
yPriceMagic,
kongEndpoint,
},
future: {
experimental_faster: true,
Expand Down
67 changes: 60 additions & 7 deletions src/components/veYFI-calculator/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,65 @@ 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}`)
if (!response.ok) {
console.error('Failed to fetch token price')
return null
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 undefined
}

const amount = Number(formatUnits(BigInt(value), Number(decimals)))
return Number.isFinite(amount) ? amount : undefined
}

export async function fetchVaultSharePrice(
kongEndpoint: string,
address: string
) {
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 tvl = data.tvl?.close
const pricePerShare = formatScaledAmount(data.pricePerShare, data.decimals)

if (
!totalAssets ||
!tvl ||
!pricePerShare ||
totalAssets <= 0 ||
tvl <= 0 ||
pricePerShare <= 0
) {
return undefined
}

const sharePrice = pricePerShare * (tvl / totalAssets)
return Number.isFinite(sharePrice) ? sharePrice : undefined
} catch (error) {
console.error('Failed to fetch vault snapshot', error)
return undefined
}
const data = await response.json()
return data
}
64 changes: 43 additions & 21 deletions src/components/veYFI-calculator/veYFI-calculator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
import {
fetchVeYFISupply,
fetchAllGaugeData,
fetchTokenPrice,
fetchVaultSharePrice,
fetchLiquidLockerVeYFIBalance,
} from './fetch'
import BoostChart from './BoostChart'
Expand All @@ -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<number>(0)
Expand All @@ -73,6 +72,9 @@ const VeYFICalculator: React.FC = () => {
const [selectedVaultSharePrice, setSelectedVaultSharePrice] = useState<
number | undefined
>(undefined)
const [vaultPriceError, setVaultPriceError] = useState<string | undefined>(
undefined
)
const [depositAmount, setDepositAmount] = useState<number | string>('')
const [depositAmountInUSD, setDepositAmountInUSD] = useState<number | string>(
''
Expand All @@ -99,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 () => {
Expand Down Expand Up @@ -139,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)
Expand All @@ -159,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)
Expand All @@ -187,15 +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 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
if (
vaultSharePrice === undefined ||
!Number.isFinite(vaultSharePrice) ||
vaultSharePrice <= 0
) {
setVaultPriceError('Vault price unavailable')
}
setSelectedVaultSharePrice(vaultSharePrice)
}
Comment thread
rossgalloway marked this conversation as resolved.
setShowChart1(false)
Expand All @@ -205,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
Expand All @@ -229,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,
Expand All @@ -255,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
Expand Down Expand Up @@ -316,6 +334,7 @@ const VeYFICalculator: React.FC = () => {
))}
</SelectContent>
</Select>
{vaultPriceError && <p>{vaultPriceError}</p>}
</div>
<div style={{ flexDirection: 'column', width: '100%' }}>
{/* <Label>Enter Amount of veYFI</Label> */}
Expand Down Expand Up @@ -382,6 +401,7 @@ const VeYFICalculator: React.FC = () => {
onClick={handleCalculateButton1Click}
disabled={
!selectedVault ||
!hasValidVaultSharePrice ||
(useVeYfiCalculator
? isNaN(Number(veYFIFromLock)) || !veYFIFromLock
: isNaN(Number(veYFIAmount)) || !veYFIAmount)
Expand Down Expand Up @@ -482,6 +502,7 @@ const VeYFICalculator: React.FC = () => {
))}
</SelectContent>
</Select>
{vaultPriceError && <p>{vaultPriceError}</p>}
</div>
<div
style={{
Expand Down Expand Up @@ -539,6 +560,7 @@ const VeYFICalculator: React.FC = () => {
onClick={handleCalculateButton2Click}
disabled={
!selectedVault ||
!hasValidVaultSharePrice ||
isNaN(Number(depositAmount)) ||
!depositAmount
}
Expand Down
24 changes: 8 additions & 16 deletions src/ethereum/publicRpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -58,24 +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
}
}

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}`
rpcUris[chainId] = trimmedValue
}

return rpcUris
Expand Down
Loading