seamless-protocol / seamless-interface

https://seamless-interface.vercel.app
Other
7 stars 4 forks source link

Total Earned Yield from Yield Bearing Strategies [My Dashboard] #434

Open rcqiao opened 3 months ago

rcqiao commented 3 months ago

Name of feature/metric: Total Earned Yield from Yield Bearing Strategies (historical to now, in USD)

Description of feature/metric: Total value earned from yield strategies over all time, expressed in a $USD value amount. Currently, the only yield bearing strategy is the 3x wsteth/eth ILM. Therefore, this would measure a user's total historical returns from this ILM in a $USD value. This means past positions that were closed/earned need to be converted to USD and any current position profits/yields must also be converted to USD value and summed together.

In the future, this metric would sum ALL yield bearing strategies (so for example the 3x wsteth/eth ILM strategy + 4.5x wsteth/eth ILM strategy if you have positions in both).

Shown on the my dashboard page

Questions/considerations: Is it possible to show this metric as a total token number by tokens as well? (Maybe too confusing, easier to just show a sum aggregate USD value, but maybe if you expand the number it shows the breakdown by tokens? Not sure if that makes it too complicated, because strategies in the future might not always use wsteth, so this could become complicated)

Picture from design (if available): Image

Estimated Timeline:

Requirements/Data Sources: We can get this on Dune by doing some complex query. Each time user deposited we should get oracle price of deposit asset and each time user withdraw we should also do that. Profit would be: current_user_equity + total_redeem_usd - total_deposit_usd We can do this on a subgraph. In the moment of emitting deposit or withdraw events we would have handler which will query for equity and scale it with current user balance of shares.

Alternatively this can be done through subgraph.

kitanovicd commented 3 months ago

Should reward be included in calculation here or only real profit?

kitanovicd commented 3 months ago

This can be done on Subgraph. Dune is not an option because this is personalized. When writing subgraph we should make sure we also store data on subgraph properly so it can be reused in future. For example here we should probably store average cost of buying LP token. This can be done by calculating profit in underlying token and using current USD price of it or in USD (historic).

kitanovicd commented 3 months ago

There is one more way to do it without Subgraph or Dune. This can be done by going through all token transfers from wallet to strategy and by taking all mints to wallet. This means that we can take this too numbers and divide them and get average price. This would not include any super heavy calculations for client so I think it should be fine. My only concern is if user has approval on underlying asset so he is buying share with someone else's money. This edge case can make this solution buggy. Also maybe one more buggy situation is if user specifies receiver on his own. I will still think about it and if it becomes really big concern then I will roll-back to parsing deposit events from LoopStrategy contract.

fredwes commented 3 months ago

Not sure how expensive this would be RPC wise but have you considered using eth_getLogs RPC method to fetch ERC4626 Deposit/Withdraw events for a user? https://docs.alchemy.com/docs/deep-dive-into-eth_getlogs#what-are-event-signatures

kitanovicd commented 3 months ago

I tried with Moralis API to get all token transfer from and to wallet. In test scenario I tried to get all wstETH transfers to strategy contract and all strategy token transfer to connected wallet. After getting all transfers I am querying for wstETH price in that block in order to get USD value. For wallet that has only 2 transactions on contract it took couple of hundred of milliseconds. For wallet that has more then 30 transactions on strategy contract it took a bit longer then 3 seconds to calculate all this. This is done after deleting cache. Also I am not sure do we want to show USD value based on wstETH price in the moment of depositing or with current price. If we are doing it with current price it will be much faster (from 3+ seconds to 1+ second). Also if we decide to use Moralis we would probably need to go with Business plan which is around 250$ a month. Pro plan will not be enough for our needs.

I tried with eth_getLogs native method on client by using Alchemy as provider. Performance wise in worst case it took around 3 seconds to load. In other cases it was better. I think performance wise going with Alchemy will be better. We are already using Alchemy for simulations so I think that it is better to just continue with Alchemy so we don't need to add new third party dependency. It will also probably be easier to monitor cost. Here https://docs.alchemy.com/reference/compute-unit-costs we can see that eth_getLogs costs 75 CU. I tried with my test API key and I can confirm that it really costs 75 CU. @fredwes Please double check can we fit into current package on Alchemy or we need to increase it because I have not credentials. Have in mind that for each strategy we may need to call eth_getLogs 2 times. So more realistic scenario would be for example: User has 3 strategies which means 3275 every time page is loaded. Of course we will cache this a lot.