-
Notifications
You must be signed in to change notification settings - Fork 9
feat: add forward APY calculation for vaults #229
8000
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
matheus1lva
wants to merge
21
commits into
yearn:main
Choose a base branch
from
matheus1lva:feat/fapy
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
7ffaf09
halfwayt there
matheus1lva f58cc29
second part
matheus1lva 4d29b79
saving
matheus1lva 186e91a
saving again so i dont screw it
matheus1lva 1227f1b
reorg
8000
matheus1lva e1c5d3f
delete uneeded
matheus1lva 57d56f7
finish??
matheus1lva 77bba77
finish??
matheus1lva 3f8d4e6
bring stuff back
matheus1lva 446288e
im almost there
matheus1lva 2123b1d
FINALLY
matheus1lva 90680a1
FINALLY
matheus1lva de49198
FINALLY
matheus1lva 27ce289
FINALLY
matheus1lva 829ca55
FINALLY
matheus1lva 6fed935
FINALLY
matheus1lva 3b16e88
fix: debugapy
matheus1lva 53a7e62
feat: add yearn v2 and v3 vault support
matheus1lva 2e89cf4
fix some typos
matheus1lva c05f03b
fix some typos
matheus1lva f571c33
leave yearn vault apy todo for future cms implem
matheus1lva File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
164 changes: 164 additions & 0 deletions
164
packages/ingest/abis/yearn/3/vault/timeseries/fapy/hook.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import { Output, OutputSchema, SnapshotSchema, StrategySchema, StrategyThing, VaultThingsWithName, VaultThingsWithNameSchema } from 'lib/types' | ||
import { Data } from '../../../../../../extract/timeseries' | ||
import { first, query } from '../../../../../../db' | ||
import { computeChainAPY } from '../../../../../../forward' | ||
import { multicall3 } from 'lib' | ||
import { getBlock, estimateHeight } from 'lib/blocks' | ||
|
||
export const outputLabel = 'fapy' | ||
|
||
export default async function process(chainId: number, address: `0x${string}`, data: Data): Promise<Output[]> { | ||
console.info('Fapy 🧮', data.outputLabel, chainId, address, (new Date(Number(data.blockTime) * 1000)).toDateString()) | ||
|
||
let blockNumber: bigint = 0n | ||
if(data.blockTime >= BigInt(Math.floor(new Date().getTime() / 1000))) { | ||
blockNumber = (await getBlock(chainId)).number | ||
} else { | ||
blockNumber = await estimateHeight(chainId, data.blockTime) | ||
} | ||
|
||
if(!multicall3.supportsBlock(chainId, blockNumber)) { | ||
console.warn('🚨', 'block not supported', chainId, blockNumber) | ||
return [] | ||
} | ||
|
||
const vault = await first<VaultThingsWithName>(VaultThingsWithNameSchema, | ||
`select thing.*, snapshot.snapshot->>'name' as name | ||
from thing | ||
join snapshot on thing.chain_id = snapshot.chain_id and thing.address = snapshot.address | ||
where thing.chain_id = $1 AND thing.address = $2 AND thing.label = $3 AND (thing.defaults->>'yearn')::boolean = true`, | ||
[chainId, address, 'vault'] | ||
) | ||
|
||
if (!vault) return [] | ||
|
||
let strategies: StrategyThing[] = [] | ||
|
||
const snapshot = await first(SnapshotSchema, ` | ||
SELECT * | ||
FROM snapshot | ||
WHERE address = $1 | ||
`, [vault.address]) | ||
|
||
strategies = await query(StrategySchema, ` | ||
SELECT * FROM thing | ||
WHERE chain_id = $1 | ||
AND label = $2 | ||
AND address = ANY($3) | ||
`, [chainId, 'strategy', snapshot.hook.withdrawalQueue ?? snapshot.hook.strategies]) | ||
|
||
const strategiesWithIndicators = await Promise.all(strategies.map(async (strategy) => { | ||
const strategySnapshot = await first(SnapshotSchema, ` | ||
SELECT * | ||
FROM snapshot | ||
WHERE address = $1 | ||
`, [strategy.address]) | ||
|
||
return { | ||
...strategy, | ||
...strategySnapshot?.snapshot, | ||
name: strategySnapshot?.snapshot.name, | ||
token: strategySnapshot?.snapshot.token, | ||
symbol: strategySnapshot?.snapshot.symbol, | ||
rewards: strategySnapshot?.snapshot.rewards, | ||
guardian: strategySnapshot?.snapshot.guardian, | ||
blockTime: Number(strategySnapshot?.snapshot.blockTime), | ||
totalDebt: BigInt(snapshot?.snapshot.totalDebt), | ||
totalIdle: BigInt(snapshot?.snapshot.totalIdle), | ||
debtRatio: Number(snapshot?.snapshot.debtRatio), | ||
decimals: Number(snapshot?.snapshot.decimals), | ||
management: snapshot?.snapshot.management, | ||
blockNumber: BigInt(snapshot?.snapshot.blockNumber), | ||
totalAssets: BigInt(snapshot?.snapshot.totalAssets), | ||
totalSupply: BigInt(snapshot?.snapshot.totalSupply), | ||
depositLimit: BigInt(snapshot?.snapshot.depositLimit), | ||
lockedProfit: BigInt(snapshot?.snapshot.lockedProfit), | ||
managementFee: Number(snapshot?.snapshot.managementFee), | ||
pricePerShare: BigInt(snapshot?.snapshot.pricePerShare), | ||
expectedReturn: BigInt(snapshot?.snapshot.expectedReturn), | ||
performanceFee: Number(snapshot?.snapshot.performanceFee), | ||
creditAvailable: BigInt(snapshot?.snapshot.creditAvailable), | ||
debtOutstanding: BigInt(snapshot?.snapshot.debtOutstanding), | ||
DOMAIN_SEPARATOR: snapshot?.snapshot.DOMAIN_SEPARATOR, | ||
emergencyShutdown: snapshot?.snapshot.emergencyShutdown, | ||
maxAvailableShares: BigInt(snapshot?.snapshot.maxAvailableShares), | ||
availableDepositLimit: BigInt(snapshot?.snapshot.availableDepositLimit), | ||
lockedProfitDegradation: BigInt(snapshot?.snapshot.lockedProfitDegradation), | ||
localKeepCRV: BigInt(strategySnapshot?.snapshot.localKeepCRV), | ||
apiVersion: strategySnapshot?.snapshot.apiVersion | ||
} | ||
})) | ||
|
||
const vaultAPY = await computeChainAPY(vault, 1, strategiesWithIndicators) | ||
|
||
if(vaultAPY) { | ||
return OutputSchema.array().parse([ | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultAPRType', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.type | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultPointsWeekAgo', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.points?.weekAgo | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultPointsMonthAgo', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.points?.monthAgo | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultPointsInception', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.points?.inception | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultPricePerShareToday', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.pricePerShare?.today | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultPricePerShareWeekAgo', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.pricePerShare?.weekAgo | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultPricePerShareMonthAgo', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.pricePerShare?.monthAgo | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultFeesPerformance', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.fees?.performance | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'vaultFeesManagement', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.fees?.management | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'forwardAPRType', | ||
blockNumber, blockTime: data.blockTime, value: vaultAPY.forwardAPY?.type | ||
}, | ||
{ | ||
chainId, address, label: data.outputLabel, component: 'forwardNetAPY', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.netAPY) | ||
}, { | ||
chainId, address, label: data.outputLabel, component: 'forwardBoost', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.boost) | ||
}, { | ||
chainId, address, label: data.outputLabel, component: 'poolAPY', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.poolAPY) | ||
}, { | ||
chainId, address, label: data.outputLabel, component: 'boostedAPR', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.boostedAPR) | ||
}, { | ||
chainId, address, label: data.outputLabel, component: 'baseAPR', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.baseAPR) | ||
}, { | ||
chainId, address, label: data.outputLabel, component: 'rewardsAPY', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.rewardsAPY) | ||
}, { | ||
chainId, address, label: data.outputLabel, component: 'cvxAPR', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.cvxAPR) | ||
}, { | ||
chainId, address, label: data.outputLabel, component: 'keepCRV', | ||
blockNumber, blockTime: data.blockTime, value: Number(vaultAPY.forwardAPY?.keepCRV) | ||
}]) | ||
} | ||
|
||
return [] | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Load environment variables first | ||
import 'lib/global' | ||
import path from 'path' | ||
import dotenv from 'dotenv' | ||
|
||
const envPath = path.join(__dirname, '../..', '.env') | ||
dotenv.config({ path: envPath }) | ||
|
||
// Other imports after environment is loaded | ||
import { rpcs } from 'lib/rpcs' | ||
import process, { outputLabel } from './abis/yearn/3/vault/timeseries/fapy/hook' | ||
import { Data } from './extract/timeseries' | ||
import { cache } from 'lib' | ||
import 'lib/global' | ||
|
||
// Vault data provided by the user | ||
const VAULT_ADDRESS = '0xf165a634296800812B8B0607a75DeDdcD4D3cC88' as `0x${string}` | ||
const CHAIN_ID = 1 // Ethereum mainnet | ||
|
||
// Create sample data | ||
const sampleData: Data = { | ||
10000 abiPath: 'yearn/3/vault', | ||
chainId: CHAIN_ID, | ||
address: VAULT_ADDRESS, | ||
outputLabel, | ||
blockTime: BigInt(Math.floor(Date.now() / 1000) - 3600) | ||
} | ||
|
||
// Enable more detailed logging | ||
console.debug = console.log | ||
|
||
// Add debugging points | ||
const run = async () => { | ||
await rpcs.up() | ||
await cache.up() | ||
console.log('Starting debugger for fapy hook') | ||
console.log('Input parameters:', { | ||
chainId: CHAIN_ID, | ||
address: VAULT_ADDRESS, | ||
blockTime: new Date(Number(sampleData.blockTime) * 1000).toISOString() | ||
}) | ||
|
||
try { | ||
const result = await process(CHAIN_ID, VAULT_ADDRESS, sampleData) | ||
console.log('Result:', result) | ||
return [] | ||
} catch (error) { | ||
console.error('Error during processing:', error) | ||
if (error instanceof Error) { | ||
console.error('Error stack:', error.stack) | ||
} | ||
return | ||
} | ||
} | ||
|
||
run() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.