From 83b33c245cab5911b1b4f9043da8a647902663a9 Mon Sep 17 00:00:00 2001 From: jackburrus Date: Tue, 15 Oct 2024 12:24:28 -0600 Subject: [PATCH 1/7] supply apy working --- apps/hyperdrive-trading/package.json | 4 +- .../src/ui/rewards/useMorphoRate.ts | 113 ++++++++++++++++- .../src/ui/rewards/useRewards.ts | 28 +++- packages/hyperdrive-appconfig/src/index.ts | 1 + yarn.lock | 120 +++++++++++++++++- 5 files changed, 255 insertions(+), 11 deletions(-) diff --git a/apps/hyperdrive-trading/package.json b/apps/hyperdrive-trading/package.json index 12db32877..9ea49ce0d 100644 --- a/apps/hyperdrive-trading/package.json +++ b/apps/hyperdrive-trading/package.json @@ -28,10 +28,10 @@ }, "dependencies": { "@delvtech/fixed-point-wasm": "^0.0.6", + "@delvtech/hyperdrive-appconfig": "^0.0.1", "@delvtech/hyperdrive-viem": "^3.0.6", "@headlessui/react": "^2.1.5", "@heroicons/react": "^2.0.16", - "@delvtech/hyperdrive-appconfig": "^0.0.1", "@radix-ui/react-tooltip": "^1.1.2", "@rainbow-me/rainbowkit": "^2.1.3", "@rollbar/react": "^0.11.1", @@ -52,6 +52,8 @@ "daisyui": "^4.12.2", "dnum": "^2.9.0", "fuse.js": "^7.0.0", + "graphql": "^16.9.0", + "graphql-request": "^7.1.0", "lodash.sortby": "^4.7.0", "process": "^0.11.10", "react": "^18.2.0", diff --git a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts index 8c694bfdc..701c2ed75 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts @@ -1,7 +1,13 @@ import { fixed, FixedPoint } from "@delvtech/fixed-point-wasm"; +import { + HyperdriveConfig, + WELL_ICON_URL, +} from "@delvtech/hyperdrive-appconfig"; import { useQuery } from "@tanstack/react-query"; import { Address } from "viem"; +import { gql, request } from "graphql-request"; + const marketPoolIds: Record = { // Key: Hyperdrive contract address for the market // Value: Corresponding Morpho vault address (for vault rewards) or pool id (for market rewards) @@ -39,7 +45,7 @@ export function useMorphoRate({ retry: 3, queryFn: async () => { const response = await fetch( - `https://rewards.morpho.org/v1/programs/?chains=${chainId}&active=true&type=uniform-reward`, + `https://rewards.morpho.org/v1/programs/?chains=${chainId}&active=true&type=uniform-reward` ); const result = await response.json(); return result.data[0]; @@ -51,7 +57,7 @@ export function useMorphoRate({ if (rewardsData) { const poolId = marketPoolIds[hyperdriveAddress]; let matchingRate = rewardsData.current_rates.find((rate) => - rate.pool_ids.some((id) => id.toLowerCase().startsWith(poolId)), + rate.pool_ids.some((id) => id.toLowerCase().startsWith(poolId)) )?.per_dollar_per_year; // If there is no matching rate, just use the first one in the current_rates array @@ -67,3 +73,106 @@ export function useMorphoRate({ morphoRate, }; } + +const vaultAddresses: Record< + Address, + { vaultAddress: string; assetIcon: string } +> = { + // Key: Hyperdrive contract address for the market + // Value: Corresponding Morpho vault address (for vault rewards) or pool id (for market rewards) + // Market: 182d Moonwell Flagship ETH + "0xceD9F810098f8329472AEFbaa1112534E96A5c7b": { + vaultAddress: "0xa0E430870c4604CcfC7B38Ca7845B1FF653D0ff1", + assetIcon: WELL_ICON_URL, + }, +}; + +const endpoint = "https://blue-api.morpho.org/graphql"; + +// Define the expected type for the GraphQL response +type SupplyRewardsResponse = { + vault: { + state: { + rewards: { + supplyApr: number; + amountPerSuppliedToken: number; + yearlySupplyTokens: number; + asset: { + name: string; + logoURI: string; + }; + }[]; + }; + }; +}; + +export function useMorphoVaultRewards({ + hyperdrive, + enabled, +}: { + hyperdrive: HyperdriveConfig; + enabled: boolean; +}): void { + const morphoVault = vaultAddresses[hyperdrive.address]; + const { data: vaultRewardsData } = useQuery({ + queryKey: [ + "morphoVaultRewards", + hyperdrive.address, + morphoVault?.vaultAddress, + hyperdrive.chainId, + ], + enabled, + staleTime: Infinity, + retry: 3, + queryFn: async () => { + const vaults = await request<{ + vaults: { + items: { + address: string; + id: string; + }[]; + }; + }>( + endpoint, + gql` + query Vaults { + vaults { + items { + address + id + } + } + } + ` + ); + const vaultId = vaults?.vaults?.items?.find( + (vault) => vault.address === morphoVault?.vaultAddress + )?.id; + + const supplyRewards: SupplyRewardsResponse = await request( + endpoint, + gql` + query SupplyRewards($vaultId: String!) { + vault(id: $vaultId) { + state { + rewards { + supplyApr + amountPerSuppliedToken + yearlySupplyTokens + asset { + name + logoURI + } + } + } + } + } + `, + { vaultId } + ); + const supplyRewardsAPY = + supplyRewards?.vault?.state?.rewards?.[0]?.supplyApr; + }, + }); + // console.log(vaultRewardsData, "vaultRewardsData"); +} diff --git a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts index 135bc04b9..ab6afe37a 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts @@ -1,5 +1,8 @@ import { HyperdriveConfig } from "@delvtech/hyperdrive-appconfig"; -import { useMorphoRate } from "src/ui/rewards/useMorphoRate"; +import { + useMorphoRate, + useMorphoVaultRewards, +} from "src/ui/rewards/useMorphoRate"; import { Address } from "viem"; import { base, linea, mainnet } from "viem/chains"; @@ -20,6 +23,13 @@ const eligibleMarketsForMorphoRewards: Record = { ], }; +const eligibleMarketsForMorphoVaultRewards: Record = { + [base.id]: [ + // 182d Moonwell Flagship ETH + "0xceD9F810098f8329472AEFbaa1112534E96A5c7b", + ], +}; + const eligibleMarketsForLineaRewards: Record = { [linea.id]: [ // 182d KelpDAO rsETH @@ -29,7 +39,7 @@ const eligibleMarketsForLineaRewards: Record = { ], }; -type RewardType = "MorphoFlatRate" | "LineaLXPL"; +type RewardType = "MorphoFlatRate" | "MorphoVault" | "LineaLXPL"; type Reward = { id: RewardType; @@ -43,7 +53,15 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { hyperdriveAddress: hyperdrive.address, enabled: eligibleMarketsForMorphoRewards[hyperdrive.chainId]?.includes( - hyperdrive.address, + hyperdrive.address + ) ?? false, + }); + + const morphoVaultRate = useMorphoVaultRewards({ + hyperdrive, + enabled: + eligibleMarketsForMorphoVaultRewards[base.id]?.includes( + hyperdrive.address ) ?? false, }); @@ -52,7 +70,7 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { // Add any morpho rewards for this market if ( eligibleMarketsForMorphoRewards[hyperdrive.chainId]?.includes( - hyperdrive.address, + hyperdrive.address ) ) { const morphoReward: Reward = { @@ -70,7 +88,7 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { // Add any linea rewards for this market if ( eligibleMarketsForLineaRewards[hyperdrive.chainId]?.includes( - hyperdrive.address, + hyperdrive.address ) ) { const lineaReward: Reward = { diff --git a/packages/hyperdrive-appconfig/src/index.ts b/packages/hyperdrive-appconfig/src/index.ts index 834ab5560..aba6b92be 100644 --- a/packages/hyperdrive-appconfig/src/index.ts +++ b/packages/hyperdrive-appconfig/src/index.ts @@ -24,6 +24,7 @@ export type { HyperdriveConfig } from "src/hyperdrives/HyperdriveConfig"; // tokens export type { TokenConfig } from "src/tokens/getTokenConfig"; +export { WELL_ICON_URL } from "src/tokens/tokenIconsUrls"; // yield sources export { yieldSources } from "src/yieldSources"; diff --git a/yarn.lock b/yarn.lock index f2dd35998..4eb0c3c4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2700,6 +2700,11 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.7.tgz#d0ece53ce99ab5a8e37ebdfe5e32452a2bfc073e" integrity sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA== +"@graphql-typed-document-node/core@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + "@gsap/react@^2.1.0": version "2.1.0" resolved "https://registry.yarnpkg.com/@gsap/react/-/react-2.1.0.tgz#fe65901d64c00d2eea4e3e8b571ae293d781622f" @@ -3070,6 +3075,30 @@ superstruct "^1.0.3" uuid "^9.0.1" +"@molt/command@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@molt/command/-/command-0.9.0.tgz#3c77efe435beb6062da8ba96097f8f82e9bee51c" + integrity sha512-1JI8dAlpqlZoXyKWVQggX7geFNPxBpocHIXQCsnxDjKy+3WX4SGyZVJXuLlqRRrX7FmQCuuMAfx642ovXmPA9g== + dependencies: + "@molt/types" "0.2.0" + alge "0.8.1" + chalk "^5.3.0" + lodash.camelcase "^4.3.0" + lodash.snakecase "^4.1.1" + readline-sync "^1.4.10" + string-length "^6.0.0" + strip-ansi "^7.1.0" + ts-toolbelt "^9.6.0" + type-fest "^4.3.1" + zod "^3.22.2" + +"@molt/types@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@molt/types/-/types-0.2.0.tgz#be19a4c16d944deb93c3d8221170b88eeb9a3085" + integrity sha512-p6ChnEZDGjg9PYPec9BK6Yp5/DdSrYQvXTBAtgrnqX6N36cZy37ql1c8Tc5LclfIYBNG7EZp8NBcRTYJwyi84g== + dependencies: + ts-toolbelt "^9.6.0" + "@motionone/animation@^10.15.1", "@motionone/animation@^10.17.0": version "10.17.0" resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.17.0.tgz#7633c6f684b5fee2b61c405881b8c24662c68fca" @@ -5763,6 +5792,11 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +abitype@0.9.8: + version "0.9.8" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-0.9.8.tgz#1f120b6b717459deafd213dfbf3a3dd1bf10ae8c" + integrity sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ== + abitype@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.0.tgz#237176dace81d90d018bebf3a45cb42f2a2d9e97" @@ -5858,6 +5892,16 @@ ajv@^8.0.0, ajv@^8.9.0: require-from-string "^2.0.2" uri-js "^4.2.2" +alge@0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/alge/-/alge-0.8.1.tgz#f3d8a9ceecaf6d56981ecb2a4804a0e6dd7f4e6b" + integrity sha512-kiV9nTt+XIauAXsowVygDxMZLplZxDWt0W8plE/nB32/V2ziM/P/TxDbSVK7FYIUt2Xo16h3/htDh199LNPCKQ== + dependencies: + lodash.ismatch "^4.4.0" + remeda "^1.0.0" + ts-toolbelt "^9.6.0" + zod "^3.17.3" + algoliasearch-helper@^3.13.3: version "3.16.3" resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.16.3.tgz#38c3a18e278306f565823cc7f3dd706825b4bfb9" @@ -9665,6 +9709,20 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql-request@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-7.1.0.tgz#7b4840f977508f616f22c4168f2347c1dc580868" + integrity sha512-Ouu/lYVFhARS1aXeZoVJWnGT6grFJXTLwXJuK4mUGGRo0EUk1JkyYp43mdGmRgUVezpRm6V5Sq3t8jBDQcajng== + dependencies: + "@graphql-typed-document-node/core" "^3.2.0" + "@molt/command" "^0.9.0" + zod "^3.23.8" + +graphql@^16.9.0: + version "16.9.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" + integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== + gray-matter@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" @@ -11280,6 +11338,11 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.snakecase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" + integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw== + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -14258,6 +14321,11 @@ reading-time@^1.5.0: resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== +readline-sync@^1.4.10: + version "1.4.10" + resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b" + integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== + real-require@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" @@ -14472,6 +14540,11 @@ remark-stringify@^11.0.0: mdast-util-to-markdown "^2.0.0" unified "^11.0.0" +remeda@^1.0.0: + version "1.61.0" + resolved "https://registry.yarnpkg.com/remeda/-/remeda-1.61.0.tgz#dccd31ab75d0f02865f3ef89e4f0ce0076096464" + integrity sha512-caKfSz9rDeSKBQQnlJnVW3mbVdFgxgGWQKq1XlFokqjf+hQD5gxutLGTTY2A/x24UxVyJe9gH5fAkFI63ULw4A== + renderkid@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" @@ -15471,6 +15544,13 @@ string-argv@0.3.2: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== +string-length@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-6.0.0.tgz#1c7342bbf032129b2f80003e69f889c70231d791" + integrity sha512-1U361pxZHEQ+FeSjzqRpV+cu2vTzYeWeafXFLykiFlv4Vc0n3njgU8HrMbyik5uwm77naWMuVG8fhEF+Ovb1Kg== + dependencies: + strip-ansi "^7.1.0" + "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -15580,7 +15660,7 @@ stringify-object@^3.3.0: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -16019,6 +16099,11 @@ ts-node@^10.9.1, ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +ts-toolbelt@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz#50a25426cfed500d4a09bd1b3afb6f28879edfd5" + integrity sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w== + tsc@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/tsc/-/tsc-2.0.4.tgz#5f6499146abea5dca4420b451fa4f2f9345238f5" @@ -16229,6 +16314,11 @@ type-fest@^2.13.0, type-fest@^2.5.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== +type-fest@^4.3.1: + version "4.26.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.26.1.tgz#a4a17fa314f976dd3e6d6675ef6c775c16d7955e" + integrity sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -16305,11 +16395,16 @@ typedoc@^0.25.7: minimatch "^9.0.3" shiki "^0.14.7" -typescript@^5.0.2, typescript@^5.3.3, typescript@^5.4.4, typescript@^5.4.5, typescript@^5.5.4, typescript@~5.2.2: +typescript@^5.0.2, typescript@^5.3.3, typescript@^5.4.4, typescript@^5.4.5, typescript@^5.5.4: version "5.5.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== +typescript@~5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== + ua-parser-js@^1.0.37: version "1.0.37" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.37.tgz#b5dc7b163a5c1f0c510b08446aed4da92c46373f" @@ -16705,7 +16800,21 @@ vfile@^6.0.0, vfile@^6.0.1: unist-util-stringify-position "^4.0.0" vfile-message "^4.0.0" -viem@2.9.2, viem@^1.0.0, viem@^1.1.4, viem@^2.7.8, viem@^2.9.2: +viem@^1.0.0, viem@^1.1.4: + version "1.21.4" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.21.4.tgz#883760e9222540a5a7e0339809202b45fe6a842d" + integrity sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ== + dependencies: + "@adraffy/ens-normalize" "1.10.0" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "0.9.8" + isows "1.0.3" + ws "8.13.0" + +viem@^2.7.8, viem@^2.9.2: version "2.9.2" resolved "https://registry.yarnpkg.com/viem/-/viem-2.9.2.tgz#29bd2425222be136bf969a90dd3a8d6032221904" integrity sha512-GRakUTNiYE9W+vL+Be9JkQfzWnkczerHtSpEe2JR/jEGTYZAs4shrA4WLgiaVCI9JxpnduZhQfRWNvy2dlyP2g== @@ -17361,6 +17470,11 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== +zod@^3.17.3, zod@^3.22.2, zod@^3.23.8: + version "3.23.8" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" + integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== + zod@^3.22.4: version "3.22.4" resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" From 7557a20b6bae3f76fcee7e25b2fdd095e9be0b83 Mon Sep 17 00:00:00 2001 From: jackburrus Date: Tue, 15 Oct 2024 12:41:45 -0600 Subject: [PATCH 2/7] reward showing on tooltip --- .../src/ui/rewards/RewardsTooltip.tsx | 23 ++++++ .../src/ui/rewards/useMorphoRate.ts | 72 +++++++++---------- .../src/ui/rewards/useRewards.ts | 26 +++++-- 3 files changed, 78 insertions(+), 43 deletions(-) diff --git a/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx b/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx index 99d518557..8ec20d505 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx +++ b/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx @@ -71,6 +71,29 @@ export function RewardsTooltip({ ); + + case "MorphoVault": + return ( +
+
+ Morpho logo + {reward.name} +
+ +
+

+ +{reward.amount} +

+
+
+ ); case "LineaLXPL": return (
= { // Key: Hyperdrive contract address for the market @@ -95,8 +95,6 @@ type SupplyRewardsResponse = { state: { rewards: { supplyApr: number; - amountPerSuppliedToken: number; - yearlySupplyTokens: number; asset: { name: string; logoURI: string; @@ -112,9 +110,13 @@ export function useMorphoVaultRewards({ }: { hyperdrive: HyperdriveConfig; enabled: boolean; -}): void { +}): { + morphoVaultRewards: SupplyRewardsResponse | undefined; + isLoading: boolean; +} { const morphoVault = vaultAddresses[hyperdrive.address]; - const { data: vaultRewardsData } = useQuery({ + + const { data: morphoVaultRewards, isLoading } = useQuery({ queryKey: [ "morphoVaultRewards", hyperdrive.address, @@ -125,54 +127,52 @@ export function useMorphoVaultRewards({ staleTime: Infinity, retry: 3, queryFn: async () => { + if (!morphoVault?.vaultAddress) { + return; + } + const vaults = await request<{ - vaults: { - items: { - address: string; - id: string; - }[]; - }; + vaults: { items: { address: string; id: string }[] }; }>( endpoint, - gql` - query Vaults { - vaults { - items { - address - id - } + `query Vaults { + vaults { + items { + address + id } } - ` + }` ); + const vaultId = vaults?.vaults?.items?.find( - (vault) => vault.address === morphoVault?.vaultAddress + (vault) => vault.address === morphoVault.vaultAddress )?.id; + if (!vaultId) { + return; + } const supplyRewards: SupplyRewardsResponse = await request( endpoint, - gql` - query SupplyRewards($vaultId: String!) { - vault(id: $vaultId) { - state { - rewards { - supplyApr - amountPerSuppliedToken - yearlySupplyTokens - asset { - name - logoURI - } + `query SupplyRewards($vaultId: String!) { + vault(id: $vaultId) { + state { + rewards { + supplyApr + asset { + name + logoURI } } } } - `, + }`, { vaultId } ); - const supplyRewardsAPY = - supplyRewards?.vault?.state?.rewards?.[0]?.supplyApr; + + return supplyRewards; }, }); - // console.log(vaultRewardsData, "vaultRewardsData"); + + return { morphoVaultRewards, isLoading }; } diff --git a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts index ab6afe37a..05015ac64 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts @@ -57,13 +57,14 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { ) ?? false, }); - const morphoVaultRate = useMorphoVaultRewards({ - hyperdrive, - enabled: - eligibleMarketsForMorphoVaultRewards[base.id]?.includes( - hyperdrive.address - ) ?? false, - }); + const { morphoVaultRewards, isLoading: isMorphoVaultLoading } = + useMorphoVaultRewards({ + hyperdrive, + enabled: + eligibleMarketsForMorphoVaultRewards[base.id]?.includes( + hyperdrive.address + ) ?? false, + }); const rewards = []; @@ -99,5 +100,16 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { rewards.push(lineaReward); } + if ( + eligibleMarketsForMorphoVaultRewards[base.id]?.includes(hyperdrive.address) + ) { + const morphoVaultReward: Reward = { + id: "MorphoVault", + name: "WELL", + amount: "0", + }; + rewards.push(morphoVaultReward); + } + return rewards; } From feff8448a7d26da933bdd9a458f0f140e3e27e29 Mon Sep 17 00:00:00 2001 From: jackburrus Date: Tue, 15 Oct 2024 14:04:06 -0600 Subject: [PATCH 3/7] removed extra call --- .../src/ui/rewards/RewardsTooltip.tsx | 4 +- .../src/ui/rewards/useMorphoRate.ts | 92 +++++++------------ .../src/ui/rewards/useRewards.ts | 15 ++- 3 files changed, 49 insertions(+), 62 deletions(-) diff --git a/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx b/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx index 8ec20d505..c25d74e18 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx +++ b/apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx @@ -80,8 +80,8 @@ export function RewardsTooltip({ >
Morpho logo {reward.name} diff --git a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts index 9bac1db96..5e5dc2a4f 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts @@ -74,22 +74,20 @@ export function useMorphoRate({ }; } -const vaultAddresses: Record< - Address, - { vaultAddress: string; assetIcon: string } -> = { - // Key: Hyperdrive contract address for the market - // Value: Corresponding Morpho vault address (for vault rewards) or pool id (for market rewards) - // Market: 182d Moonwell Flagship ETH - "0xceD9F810098f8329472AEFbaa1112534E96A5c7b": { - vaultAddress: "0xa0E430870c4604CcfC7B38Ca7845B1FF653D0ff1", - assetIcon: WELL_ICON_URL, - }, -}; +const vaultAddresses: Record = + { + // Key: Hyperdrive contract address for the market + // Value: Morpho vault id and asset icon + // The vault id can be found by querying the vaults on the Morpho graphql API: https://blue-api.morpho.org/graphql + // Market: 182d Moonwell Flagship ETH + "0xceD9F810098f8329472AEFbaa1112534E96A5c7b": { + vaultId: "8f746d5a-bc4a-48ad-806d-2638ef95885f", + assetIcon: WELL_ICON_URL, + }, + }; const endpoint = "https://blue-api.morpho.org/graphql"; -// Define the expected type for the GraphQL response type SupplyRewardsResponse = { vault: { state: { @@ -115,63 +113,41 @@ export function useMorphoVaultRewards({ isLoading: boolean; } { const morphoVault = vaultAddresses[hyperdrive.address]; - + const queryEnabled = !!morphoVault?.vaultId && enabled; const { data: morphoVaultRewards, isLoading } = useQuery({ queryKey: [ "morphoVaultRewards", hyperdrive.address, - morphoVault?.vaultAddress, hyperdrive.chainId, + morphoVault?.vaultId, ], - enabled, + enabled: queryEnabled, staleTime: Infinity, retry: 3, - queryFn: async () => { - if (!morphoVault?.vaultAddress) { - return; - } - - const vaults = await request<{ - vaults: { items: { address: string; id: string }[] }; - }>( - endpoint, - `query Vaults { - vaults { - items { - address - id - } - } - }` - ); - - const vaultId = vaults?.vaults?.items?.find( - (vault) => vault.address === morphoVault.vaultAddress - )?.id; - if (!vaultId) { - return; - } - - const supplyRewards: SupplyRewardsResponse = await request( - endpoint, - `query SupplyRewards($vaultId: String!) { - vault(id: $vaultId) { - state { - rewards { - supplyApr - asset { - name - logoURI + queryFn: queryEnabled + ? async () => { + const supplyRewards: SupplyRewardsResponse = await request( + endpoint, + `query SupplyRewards($vaultId: String!) { + vault(id: $vaultId) { + state { + rewards { + supplyApr + asset { + name + logoURI + } + } } } } - } - }`, - { vaultId } - ); + }`, + { vaultId: morphoVault.vaultId } + ); - return supplyRewards; - }, + return supplyRewards; + } + : undefined, }); return { morphoVaultRewards, isLoading }; diff --git a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts index 05015ac64..5b35b9a9d 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts @@ -1,4 +1,7 @@ -import { HyperdriveConfig } from "@delvtech/hyperdrive-appconfig"; +import { + HyperdriveConfig, + WELL_ICON_URL, +} from "@delvtech/hyperdrive-appconfig"; import { useMorphoRate, useMorphoVaultRewards, @@ -45,6 +48,7 @@ type Reward = { id: RewardType; name: string; amount: string; + iconUrl?: string; }; export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { @@ -66,6 +70,8 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { ) ?? false, }); + console.log("morphoVaultRewards", morphoVaultRewards); + const rewards = []; // Add any morpho rewards for this market @@ -106,7 +112,12 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { const morphoVaultReward: Reward = { id: "MorphoVault", name: "WELL", - amount: "0", + iconUrl: WELL_ICON_URL, + amount: morphoVaultRewards?.vault?.state?.rewards[0]?.supplyApr + ? `${( + morphoVaultRewards.vault.state.rewards[0].supplyApr * 100 + ).toFixed(2)}%` + : "0%", }; rewards.push(morphoVaultReward); } From 3f43700a22aa7a7ae283cbe620c1b98cc97fac23 Mon Sep 17 00:00:00 2001 From: jackburrus Date: Tue, 15 Oct 2024 14:09:48 -0600 Subject: [PATCH 4/7] update hook --- apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts index 5e5dc2a4f..1083d5b20 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts @@ -95,7 +95,6 @@ type SupplyRewardsResponse = { supplyApr: number; asset: { name: string; - logoURI: string; }; }[]; }; @@ -135,13 +134,11 @@ export function useMorphoVaultRewards({ supplyApr asset { name - logoURI } } } } - } - }`, + }`, { vaultId: morphoVault.vaultId } ); From ae2de101b75df764654e533bdf4e3e6aff13a45f Mon Sep 17 00:00:00 2001 From: jackburrus Date: Tue, 15 Oct 2024 14:22:30 -0600 Subject: [PATCH 5/7] cleanup hook --- .../src/ui/rewards/useMorphoRate.ts | 10 +++++-- .../src/ui/rewards/useRewards.ts | 29 ++++++++----------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts index 1083d5b20..1376abc62 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts @@ -108,7 +108,9 @@ export function useMorphoVaultRewards({ hyperdrive: HyperdriveConfig; enabled: boolean; }): { - morphoVaultRewards: SupplyRewardsResponse | undefined; + morphoVaultReward: + | SupplyRewardsResponse["vault"]["state"]["rewards"][0] + | undefined; isLoading: boolean; } { const morphoVault = vaultAddresses[hyperdrive.address]; @@ -147,5 +149,9 @@ export function useMorphoVaultRewards({ : undefined, }); - return { morphoVaultRewards, isLoading }; + return { + // Return the first reward in the rewards array + morphoVaultReward: morphoVaultRewards?.vault?.state?.rewards[0], + isLoading, + }; } diff --git a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts index 5b35b9a9d..cb0be3f36 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts @@ -61,16 +61,13 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { ) ?? false, }); - const { morphoVaultRewards, isLoading: isMorphoVaultLoading } = - useMorphoVaultRewards({ - hyperdrive, - enabled: - eligibleMarketsForMorphoVaultRewards[base.id]?.includes( - hyperdrive.address - ) ?? false, - }); - - console.log("morphoVaultRewards", morphoVaultRewards); + const { morphoVaultReward } = useMorphoVaultRewards({ + hyperdrive, + enabled: + eligibleMarketsForMorphoVaultRewards[base.id]?.includes( + hyperdrive.address + ) ?? false, + }); const rewards = []; @@ -109,17 +106,15 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined { if ( eligibleMarketsForMorphoVaultRewards[base.id]?.includes(hyperdrive.address) ) { - const morphoVaultReward: Reward = { + const vaultReward: Reward = { id: "MorphoVault", - name: "WELL", + name: morphoVaultReward?.asset.name ?? "WELL", iconUrl: WELL_ICON_URL, - amount: morphoVaultRewards?.vault?.state?.rewards[0]?.supplyApr - ? `${( - morphoVaultRewards.vault.state.rewards[0].supplyApr * 100 - ).toFixed(2)}%` + amount: morphoVaultReward?.supplyApr + ? `${(morphoVaultReward.supplyApr * 100).toFixed(2)}%` : "0%", }; - rewards.push(morphoVaultReward); + rewards.push(vaultReward); } return rewards; From ff157d9f8948dda6b83f2c4a3dfb269ba995c54a Mon Sep 17 00:00:00 2001 From: jackburrus Date: Tue, 15 Oct 2024 14:26:53 -0600 Subject: [PATCH 6/7] adds changeset --- .changeset/loud-radios-roll.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/loud-radios-roll.md diff --git a/.changeset/loud-radios-roll.md b/.changeset/loud-radios-roll.md new file mode 100644 index 000000000..d43fe2ff5 --- /dev/null +++ b/.changeset/loud-radios-roll.md @@ -0,0 +1,5 @@ +--- +"@delvtech/hyperdrive-appconfig": patch +--- + +Export token icon for use in rewards modal From d25799b1e15b094c6704eaa2fc41a5add790a09c Mon Sep 17 00:00:00 2001 From: jackburrus Date: Tue, 15 Oct 2024 16:04:21 -0600 Subject: [PATCH 7/7] updates graphql query string --- .../src/ui/rewards/useMorphoRate.ts | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts index 1376abc62..ba79a5446 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useMorphoRate.ts @@ -74,22 +74,23 @@ export function useMorphoRate({ }; } -const vaultAddresses: Record = - { - // Key: Hyperdrive contract address for the market - // Value: Morpho vault id and asset icon - // The vault id can be found by querying the vaults on the Morpho graphql API: https://blue-api.morpho.org/graphql - // Market: 182d Moonwell Flagship ETH - "0xceD9F810098f8329472AEFbaa1112534E96A5c7b": { - vaultId: "8f746d5a-bc4a-48ad-806d-2638ef95885f", - assetIcon: WELL_ICON_URL, - }, - }; +const vaultAddresses: Record< + Address, + { vaultAddress: string; assetIcon: string } +> = { + // Key: Hyperdrive contract address for the market + // Value: Morpho vault address and asset icon + // Market: 182d Moonwell Flagship ETH + "0xceD9F810098f8329472AEFbaa1112534E96A5c7b": { + vaultAddress: "0xa0E430870c4604CcfC7B38Ca7845B1FF653D0ff1", + assetIcon: WELL_ICON_URL, + }, +}; const endpoint = "https://blue-api.morpho.org/graphql"; type SupplyRewardsResponse = { - vault: { + vaultByAddress: { state: { rewards: { supplyApr: number; @@ -109,18 +110,18 @@ export function useMorphoVaultRewards({ enabled: boolean; }): { morphoVaultReward: - | SupplyRewardsResponse["vault"]["state"]["rewards"][0] + | SupplyRewardsResponse["vaultByAddress"]["state"]["rewards"][0] | undefined; isLoading: boolean; } { const morphoVault = vaultAddresses[hyperdrive.address]; - const queryEnabled = !!morphoVault?.vaultId && enabled; + const queryEnabled = !!morphoVault?.vaultAddress && enabled; const { data: morphoVaultRewards, isLoading } = useQuery({ queryKey: [ "morphoVaultRewards", hyperdrive.address, hyperdrive.chainId, - morphoVault?.vaultId, + morphoVault?.vaultAddress, ], enabled: queryEnabled, staleTime: Infinity, @@ -129,21 +130,22 @@ export function useMorphoVaultRewards({ ? async () => { const supplyRewards: SupplyRewardsResponse = await request( endpoint, - `query SupplyRewards($vaultId: String!) { - vault(id: $vaultId) { + `query SupplyRewards($address: String!, $chainId: Int!) { + vaultByAddress(address: $address, chainId: $chainId) { + address state { rewards { supplyApr asset { - name + address + symbol } } } } }`, - { vaultId: morphoVault.vaultId } + { address: morphoVault.vaultAddress, chainId: hyperdrive.chainId } ); - return supplyRewards; } : undefined, @@ -151,7 +153,7 @@ export function useMorphoVaultRewards({ return { // Return the first reward in the rewards array - morphoVaultReward: morphoVaultRewards?.vault?.state?.rewards[0], + morphoVaultReward: morphoVaultRewards?.vaultByAddress?.state?.rewards[0], isLoading, }; }