GithubHelp home page GithubHelp logo

olympus-protocol-metrics-subgraph's Introduction

OHM Discord Branches Coverage Badge Lines Coverage Badge Statements Coverage Badge Functions Coverage Badge

This is the front-end repo for Olympus.

🔧 Setting up Local Development

Required:

$ git clone https://github.com/OlympusDAO/olympus-frontend.git
$ cd olympus-frontend

# set up your environment variables
# read the comments in the .env files for what is required/optional
$ cp .env.example .env

# fill in your own values in .env, then =>
$ yarn
$ yarn start

# Set up Husky (for pre-commit hooks) by running:
$ yarn prepare

The site is now running at http://localhost:3000! Open the source code and start editing!

Testing

We use the Vitest test driver for unit tests, snapshot tests and e2e tests.

To run tests in interactive mode during development:

yarn test
# or
yarn test --ui

Unit Testing

Unit test files are co-located with the source code files that they test and follow the naming convention *.unit.test.ts. For example unit tests for OriginalSourceFile.ts are located in OriginalSourceFile.unit.test.ts. Valid extensions for test files are .js (JavaScript), .ts (TypeScript), .jsx (React JSX), .tsx (React TSX).

To run all unit test and see a coverage report:

yarn test:unit

Note that the focus of unit testing is to exercise all paths through the code hosted in this repo and only code hosted in this repo. To the extent possible, unit tests should abstract out dependencies such as remote API calls as well as crypto wallet APIs via mock functions.

Coverage thresholds are enforced via CI checks. If a new PR introduces regression in code coverage, the CI will fail. The goal is to keep us at a minimum level of test automation coverage as we introduce new code into the repo. To see the current coverage thresholds, see the coverageThreshold in package.json.

For integration testing automation that runs browser and remote API code as well as our own code, see the End-to-end (E2E) testing section below.

Mocking Remote API Calls

Unit tests should minimize dependency on remote API calls. Remote API calls slow down test execution and they also occasionally error, which may fail tests for reasons outside the app code being tested. Live API calls should be tested in End-to-end/Integration tests.

Here is an example unit test that conditionally mocks API calls.

Generative Testing

We use fast-check for generative testing which provides property-based coverage for ranges of input values. Here is an example of a unit test case in this repo that uses generative testing.

Snapshot Testing

We use Snapshot tests to make sure the UI does not change unexpectedly. When you make changes to the UI (intentionally), you likely will have to update the Snapshots. You can do so by running: yarn snapshot.

Here is an example snapshot test and here is the correspoding recorded snapshot. Keep in mind that for snapshot tests to be meaningful, they have to pre-populate components with variety of data sets (realistic, edge case, invalid).

Here is a good blog post about testing React components with generative data sets.

React Component Testing

We use React Testing Library to test behavior of UI components. Here is an example component test. Here is a useful cheat sheet.

Mocking React Hooks

When testing components that use React Hooks to third party libraries such as React Query or Web3Provider, it is sometimes convenient to mock these hooks in order to simulate various data inputs and edge cases.

Here is an example test case that shows how to mock React Hooks that use Web3Provider and React Query APIs.

Troubleshooting

If all tests are failing in your local environment (in particular, due to a "cannot find module" error with node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/interopRequireDefault.js), but they should be passing (and the CI tests are passing), it's likely to be an issue with your local cache. Run the following command: yarn test --clearCache

End-to-end testing

Puppeteer (with the Dappeteer addition) is used to do browser-based end-to-end testing.

To run the tests:

  • Run the frontend, using yarn start
  • In another terminal, run the tests, using yarn test:e2e

Architecture/Layout

The files/folder structure are a WIP and may contain some unused files. The project is rapidly evolving so please update this section if you see it is inaccurate!

./src/
├── App.tsx       // Main app page
├── abi/          // Contract ABIs
├── assets/       // Static assets (SVGs)
├── components/   // Reusable individual components
├── constants/    // Addresses & common contracts
├── helpers/      // Helper methods to use in the app
├── hooks/        // Shared reactHooks
├── themes/       // Style sheets for dark vs light theme
└── views/        // Individual Views

Theme Support

Material UI components, such as Button, can use the current theme's color scheme through the color property. For example:

 <Button variant="contained" color="primary" className="cause-give-button">
  Give Yield
 </Button>

If you wish to use a theme's color scheme manually, follow these steps:

  1. Import useTheme: import { useTheme } from "@material-ui/core/styles";
  2. Instantiate the theme: const theme = useTheme();
  3. Add a style property to the component, for example:
 <Grid item className="cause-category" style={{ backgroundColor: theme.palette.background.default }}>
 {category}
 </Grid>

For the available theme properties, take a look at the themes in src/themes.

ESLint

We use ESLint to find/automatically fix problems.

  • react-app and react-hooks/recommended are important with react stuff.
  • @typescript-eslint/recommended and @typescript-eslint/eslint-recommended as recommended defaults.
  • unused-imports to automatically remove unused imports.
  • simple-import-sort to automatically sort imports alphabetically. This is opinionated, but useful because it helps avoid merge conflicts with imports (and who doesn't like neat alphabetically sorted imports anyway).
  • @typescript-eslint/explicit-function-return-type and @typescript-eslint/explicit-module-boundary-types are turned off to prioritise inferred return types over explicit return types. This is opinionated, but often times the inference Typescript makes is good enough, and sometimes help prevents type mismatches that are a pain to debug.
  • @typescript-eslint/ban-ts-comment and @typescript-eslint/ban-ts-ignore are also turned off. This could possibly be temporary, but the ability to use @ts-ignore-like directives is certainly handy as an escape hatch as we encounter errors during the migration to TS.

Reusable Components (Component Library)

Our codebase uses a custom component library extended from Material UI to make common UI patterns easy to implement on the frontend. An up-to-date list of available components, implementation examples as well as documentation is available here:

Storybook

Contributions are welcome and encouraged to our Component Library. If you see repeated UI patterns not represented in the library, or would like to enhance functionality (such as adding assets to our Icon or Token components), you're welcome to submit a PR to the component-library project. Please fully review component documentation in Storybook before submitting a PR.

Code Generation

The react-query hooks for the Cooler Loans API are automatically generated from the OpenAPI typings. If changes are made to the API, re-generate the typings using yarn codegen. This has some steps in-between, as the code generators did not correctly handle referenced files and needed to bundle them together.

🚀 Deployment

Auto deployed on Fleek.co frontend by Cloudflare. Since it is hosted via IPFS there is no running "server" component and we don't have server sided business logic. Users are served an index.html and javascript to run our applications.

Continuous deployment

Commits to the follow branches are automatically deployed to their respective URLs.

Branch URL
master https://app.olympusdao.finance
develop https://staging.olympusdao.finance

Pull Requests: Each PR into master will get its own custom URL that is visible on the PR page. QA & validate changes on that URL before merging into the develop branch.

Cooler Loans Dashboard

The data in the Cooler Loans Dashboard is served by an API that generates time-series data not possible in a subgraph. See the cooler-loans-api repository for details.

Different endpoints are used in different circumstances:

  • Build (deployed by Fleek): production
  • Local development: dev
  • If VITE_COOLER_LOANS_API_ENDPOINT is specified in an environment variable, it will be used regardless

Treasury Dashboard

The data in the Treasury Dashboard is powered by subgraphs hosted by the Graph Protocol and served using GraphQL. There are a few limitations, however:

  • Each subgraph can index only one blockchain, so there are subgraphs deployed for each blockchain.
  • The implementation of pagination in the Graph Protocol's GraphQL server is very basic, and requires running through successive date ranges in order to piece together results.

Using infinite queries (generated by graphql-codegen), a custom paginator and custom code to combine results from different blockchains, this was previously implemented client-side. However, the code was very brittle, and sometimes suffered from stale queries.

This has since been improved by adding Wundergraph middleware (hosted on Wundergraph Cloud) that handles combining results and pagination server-side. The complete data set is then retrieved using react-query and a generated client, @olympusdao/treasury-subgraph-client.

Wundergraph Node URL

The Wundergraph client is pre-configured with the production endpoint (referred to as a public node URL).

A developer may wish to use a different endpoint during development (e.g. to test changes that are not live in production). To achieve this, prefix the yarn start command with the VITE_WG_PUBLIC_NODE_URL variable, e.g. VITE_WG_PUBLIC_NODE_URL=http://localhost:9991 yarn start. It is recommended to define the variable this way, rather than in .env, as it makes the variable override explicit.

Known Issues

The Treasury Dashboard has a notification banner to proactively communicate any known issues to users. Content is sourced from a Markdown file, and can be edited within the GitHub interface here.

If editing the production content, opt to create a new branch and pull request, so that it can be merged into production.

How to commit changes to the Known Issues Markdown file

🗣 Community and Contributions

Deploy Your Own Frontend

Deploy with Vercel Deploy to Netlify

olympus-protocol-metrics-subgraph's People

Contributors

0xjem avatar dependabot[bot] avatar drondin avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

olympus-protocol-metrics-subgraph's Issues

Improve speed of subgraph indexing

Subgraph indexing is SLOW. 3-4 days for 1 month of data.

Any time we make changes to the subgraph, it's a multi-week process to get the data live. Not cool.

Ideas:

  • Once we're on the decentralised network, pay more to indexers to speed up the pace of indexing. I'm unsure if this would make a difference.
  • Launch on Graph Substreams (release date TBC)
  • Look at other options, such as Outserv. Moralis?

Add remaining volatile assets

There are a large number of volatile assets that are not included in the subgraph. For each of them, add the following:

  • ERC20 contract address
  • Liquidity pair (to ETH, OHM or USD)

Add additional assets to Liquid Backing and apply weighting to assets where we hold high supply

Jem,

The Treasury Team has engaged with Policy on adding several assets that we see are missing from the Liquid Backing Graph and we feel should be added. Policy would like to see what Liquid Backing would be produced with these changes before they are pushed to the production site as they could dramatically impact a future RBS min target price.

Add these assets to Liquid Backing:

wBTC on ETH - 100% - Current spot price $446,508.68 
Naked USDC on ETH - 100% - Current spot price $249,917.85
Naked ETH on ETH - 100% - Current spot price $119,421.82

Apply weighted values to the following assets where Treasury has deemed that we hold so much of the circulating supply, the spot market value is not conservatives enough to all be added to liquid backing.

The formula used to derive these values was to place them against their deepest liquidity counter party asset and determine what the spot slippage was. 50% of that slippage value was taken and subtracted from the spot value creating a weighted valuation that we feel is more conservative.

JONES - 83% of Market Value towards liquid backing
KLIMA - 85% of Market Value towards liquid backing
rlBTRFLY - 89% of Market Value towards liquid backing
VSTA - 77% of Market Value towards liquid backing
BOND - 77% of Market Value towards liquid backing

If these two changes can be added and what the new liquid backing would be can be shared. Treasury and Policy will review and then determine how to push to the front end prod site.

Add by-token summary under components metrics

In order to calculate the balance/value of a particular (or all) tokens, the frontend currently needs to sum across all wallets for a particular token. This is inefficient, and the data returned by the user's browser will be the same every time. So it makes sense to pre-calculate this in the subgraph.

We'll add a *Tokens metric (e.g. treasuryMarketValueTokens) that will have a record per token, with each record representing the balance across all wallets. There will be a loss of information, but that can be obtained by querying against the *Components metric.

Remove Myso Hardcoded Value

Currently the Olympus Treasury Dash assumes there is $500k in Myso. This was done at launch.

With Cooler coming online, Jala asked that we remove this plug number.

Supporting Conversation:

image

Add Vendor and Myso Contracts to Subgraph so that the DAI Can be Counted for LB

Vendor Contract:
https://debank.com/profile/0x83234a159dbd60a32457df158fafcbdf3d1ccc08

Myso Contract:
https://debank.com/profile/0xb339953fc028b9998775c00594a74dd1488ee2c6

DAI located in these contracts was taken from Treasury and deployed into the Lending Markets. The liquid portion of the DAI should be counted towards liquid backing. The OHM should not.

If you can get these added and kick off a reindex, that will allow for us to get accurate LB numbers to evaluate if we need a parameter change on Monday or not.

Implement viewable documentation

There is now extensive documentation in the codebase, which should help non-technical people to understand how the metrics are calculated. Documentation should be automatically generated and hosted, so that it can be reviewed.

JSDoc is an option, and seems to also support linking between functions.

Gracefully handle contracts before starting block

We don't currently have a clean way of handling contracts prior to their starting block:

  • ERC20 contracts have a defined starting block constant, and the ERC20 helper function will return null if prior to that (which prevents further operations). This requires manual configuration, which isn't ideal.
  • Liquidity pairs don't have any such protection

Additionally, there is plenty of code (e.g. getUSDRateUniswapV3) that expects a contract to bind and work after that. Error conditions (such as being before the starting block) should be handled gracefully, instead of throwing an error.

Implement CSV output from GraphQL

Policy/treasury team would like to get the output in a CSV format in order to make it easier to analyse.

The GraphQL output or JSON could be easily converted into a CSV format, however an apparent limitation of the subgraph library means that we can't return custom types from a metric. The closest option is an array of strings (which is what we do). This isn't valid JSON, so conversion doesn't work without manual steps.

Defining multiple price lookup paths results in infinite loop

With the new price lookup infrastructure used in chain-specific subgraphs (#81 ), defining multiple price lookup paths will result in an infinite loop.

For example in

new PriceHandlerBalancer([ERC20_MAGIC, ERC20_USDC], BALANCER_VAULT, LP_BALANCER_POOL_MAGIC_USDC, getContractName),
there are two paths to look up the price of MAGIC:

  • MAGIC-USDC
  • MAGIC-wETH

Removing the MAGIC-wETH price handler fixes the issue.

Unlocked vlCVX is missing in treasury assets

The volatile assets dropped by $6m from 3rd August 2022 to 4th August 2022, coinciding with the unlocking of vlCVX.

Discussion here: https://discord.com/channels/838651642190495804/928504031960256542/1004697028787445880

Cause:

  • We've been treating vlCVX as a standard ERC20 token and getting the balance using balanceOf. This reports the locked balance, but does not report the unlocked and un-withdrawn balance.
  • lockedBalanceOf returns the unlocked + locked balance, or alternatively, we can call lockedBalances and get a struct with total/unlockable/locked

TBC whether to differentiate between locked and unlocked balances (e.g. "vlCVX (Locked)" and "vlCVX (Unlocked)")

Add BTRFLY v2 and rlBTRFLY to Treasury Dashboard

We have recently received our first disbursements from Redacted Cartel for our Private Funding of their Protocol. Please add the following Tokens to the Treasury Dashboard marked as Volatile Assets. They should not be included in Liquid Backing as we own so much of the supply, they can't be considered entirely liquid.

rlBTRFLY Transaction:
https://etherscan.io/tx/0x6db8bcb6064193d736d962cd9c2556bf9dc873aae93376edccedab10fb3eb7f4

BTRFLY Token - 0xc55126051B22eBb829D00368f4B12Bde432de5Da
rlBTRFLY Token - 0x742B70151cd3Bc7ab598aAFF1d54B90c3ebC6027

Subgraph should report more recent blocks

The latest block that is reported by the subgraph tends to lag (I noticed 1 1/2 hours), despite the indexing having happened. Look at what causes this, so that the latest indexed block is always returned.

Change Coolered DAI description

In protocol metrics on the dashboard (https://app.olympusdao.finance/#/dashboard) in the table for Holdings, the entry "DAI - Borrowed Through Cooler Loans" should be renamed to "DAI - Loaned out Through Cooler Loans" or "DAI - Lent Through Cooler Loans" as the dashboard is showing the balance sheet from treasury's perspective. Current description can lead new readers to think that DAI is borrowed by the treasury. (example: https://discord.com/channels/798328113087119371/1083661539648745483/1181355122169757788)

Index token holders

Edgecaser is asking if we can get this within 45 days (mid-September)

  • Ethereum mainnet only
  • All tokens and versions
  • Dating from the launch of v2 (December 2021)

Need to look at how to do this. Track all transfers and maintain a balance?

Implement lookup of stablecoin prices

We currently assume that a stablecoin is priced at $1, which forms the basis of most of the other price lookups.

Instead, we should have some way to look up the stablecoin price (or treat it as a volatile token).

Account for Contract Locked Treasury Assets in Third Party Contracts

json mentioned that there are 'Locked' assets that are Olympus owned but exist in third party contract. This makes them largely illiquid but technically count towards Treasury Held. As such, we need to sort how we want to characterize them.

TreasureDAO - veMAGIC
Convex - vlCVX
Curve FXS - veFXS
Fantom - inSPIRIT

Beethoven?

Add BAL in the Treasury Multisig To Market Assets Graph and inclusion in Backing

Olympus DAO has been incentivizing its Liquidity Pools via AURA which provides the returns in the form of AURA and BAL. AURA is getting properly characterized on the Treasury Dashboard but the 60k in BAL does seem to be appearing and therefore, is not included in Liquid Backing.

Likely, BAL will get sold for wETH but in the event that it is held for a prolonged period of time, we want to make sure it does not impact LB.

Add price lookup for cvxFXS

This isn't possible with the current setup, as the only liquidity pool available is cvxFXS-FXS, and that would require our price lookup functionality to support multiple levels of price lookup, i.e. cvxFXS-FXS and (FXS-ETH or FXS-USDC).

Add ARB to the Treasury Subgraph

image

We have received our ARB Distribution from the Arbitrum One Foundation so should be getting picked up in that allocator:

0x012bbf0481b97170577745d2167ee14f63e2ad4c

Shift to Balancer for OHM price lookup

If OIP-103 passes, the Balancer pool will gradually become the pool with the greatest liquidity, and will therefore be preferable for determining the price.

A block will need to be chosen, after which the Balancer OHM-DAI-ETH pool (new one?) will be used for OHM price lookups.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.