diff --git a/src/components/withdrawModal.tsx b/src/components/withdrawModal.tsx
index 99f67d74..b868e3f1 100644
--- a/src/components/withdrawModal.tsx
+++ b/src/components/withdrawModal.tsx
@@ -106,11 +106,11 @@ export function WithdrawModal({ position, onClose, refetch }: ModalProps): JSX.E
{' '}
diff --git a/src/constants/chartColors.ts b/src/constants/chartColors.ts
new file mode 100644
index 00000000..397f8329
--- /dev/null
+++ b/src/constants/chartColors.ts
@@ -0,0 +1,26 @@
+export const CHART_COLORS = {
+ supply: {
+ stroke: '#3B82F6',
+ gradient: {
+ start: '#3B82F6',
+ startOpacity: 0.3,
+ endOpacity: 0,
+ },
+ },
+ borrow: {
+ stroke: '#10B981',
+ gradient: {
+ start: '#10B981',
+ startOpacity: 0.3,
+ endOpacity: 0,
+ },
+ },
+ rateAtUTarget: {
+ stroke: '#F59E0B',
+ gradient: {
+ start: '#F59E0B',
+ startOpacity: 0.3,
+ endOpacity: 0,
+ },
+ },
+} as const;
diff --git a/src/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf b/src/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf
new file mode 100755
index 00000000..994761f2
Binary files /dev/null and b/src/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf differ
diff --git a/src/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf b/src/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf
new file mode 100755
index 00000000..1b3d7f27
Binary files /dev/null and b/src/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf differ
diff --git a/src/fonts/JetBrains_Mono/OFL.txt b/src/fonts/JetBrains_Mono/OFL.txt
new file mode 100755
index 00000000..3f348475
--- /dev/null
+++ b/src/fonts/JetBrains_Mono/OFL.txt
@@ -0,0 +1,93 @@
+Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+https://openfontlicense.org
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/src/fonts/JetBrains_Mono/README.txt b/src/fonts/JetBrains_Mono/README.txt
new file mode 100755
index 00000000..534de33e
--- /dev/null
+++ b/src/fonts/JetBrains_Mono/README.txt
@@ -0,0 +1,79 @@
+JetBrains Mono Variable Font
+============================
+
+This download contains JetBrains Mono as both variable fonts and static fonts.
+
+JetBrains Mono is a variable font with this axis:
+ wght
+
+This means all the styles are contained in these files:
+ JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf
+ JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf
+
+If your app fully supports variable fonts, you can now pick intermediate styles
+that aren’t available as static fonts. Not all apps support variable fonts, and
+in those cases you can use the static font files for JetBrains Mono:
+ JetBrains_Mono/static/JetBrainsMono-Thin.ttf
+ JetBrains_Mono/static/JetBrainsMono-ExtraLight.ttf
+ JetBrains_Mono/static/JetBrainsMono-Light.ttf
+ JetBrains_Mono/static/JetBrainsMono-Regular.ttf
+ JetBrains_Mono/static/JetBrainsMono-Medium.ttf
+ JetBrains_Mono/static/JetBrainsMono-SemiBold.ttf
+ JetBrains_Mono/static/JetBrainsMono-Bold.ttf
+ JetBrains_Mono/static/JetBrainsMono-ExtraBold.ttf
+ JetBrains_Mono/static/JetBrainsMono-ThinItalic.ttf
+ JetBrains_Mono/static/JetBrainsMono-ExtraLightItalic.ttf
+ JetBrains_Mono/static/JetBrainsMono-LightItalic.ttf
+ JetBrains_Mono/static/JetBrainsMono-Italic.ttf
+ JetBrains_Mono/static/JetBrainsMono-MediumItalic.ttf
+ JetBrains_Mono/static/JetBrainsMono-SemiBoldItalic.ttf
+ JetBrains_Mono/static/JetBrainsMono-BoldItalic.ttf
+ JetBrains_Mono/static/JetBrainsMono-ExtraBoldItalic.ttf
+
+Get started
+-----------
+
+1. Install the font files you want to use
+
+2. Use your app's font picker to view the font family and all the
+available styles
+
+Learn more about variable fonts
+-------------------------------
+
+ https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
+ https://variablefonts.typenetwork.com
+ https://medium.com/variable-fonts
+
+In desktop apps
+
+ https://theblog.adobe.com/can-variable-fonts-illustrator-cc
+ https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
+
+Online
+
+ https://developers.google.com/fonts/docs/getting_started
+ https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
+ https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
+
+Installing fonts
+
+ MacOS: https://support.apple.com/en-us/HT201749
+ Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
+ Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
+
+Android Apps
+
+ https://developers.google.com/fonts/docs/android
+ https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
+
+License
+-------
+Please read the full license text (OFL.txt) to understand the permissions,
+restrictions and requirements for usage, redistribution, and modification.
+
+You can use them in your products & projects – print or digital,
+commercial or otherwise.
+
+This isn't legal advice, please consider consulting a lawyer and see the full
+license for all details.
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-Bold.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Bold.ttf
new file mode 100755
index 00000000..1926c804
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Bold.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-BoldItalic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-BoldItalic.ttf
new file mode 100755
index 00000000..a4477513
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-BoldItalic.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraBold.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraBold.ttf
new file mode 100755
index 00000000..0c5f863f
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraBold.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraBoldItalic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraBoldItalic.ttf
new file mode 100755
index 00000000..d62fc3c3
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraBoldItalic.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraLight.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraLight.ttf
new file mode 100755
index 00000000..605f79d0
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraLight.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraLightItalic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraLightItalic.ttf
new file mode 100755
index 00000000..befe9d20
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ExtraLightItalic.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-Italic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Italic.ttf
new file mode 100755
index 00000000..8cf794ab
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Italic.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-Light.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Light.ttf
new file mode 100755
index 00000000..9d5d8a5d
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Light.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-LightItalic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-LightItalic.ttf
new file mode 100755
index 00000000..4c91d3e0
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-LightItalic.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-Medium.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Medium.ttf
new file mode 100755
index 00000000..ad71d92b
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Medium.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-MediumItalic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-MediumItalic.ttf
new file mode 100755
index 00000000..4c96cc57
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-MediumItalic.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-Regular.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Regular.ttf
new file mode 100755
index 00000000..436c982f
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Regular.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-SemiBold.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-SemiBold.ttf
new file mode 100755
index 00000000..b00a6485
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-SemiBold.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-SemiBoldItalic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-SemiBoldItalic.ttf
new file mode 100755
index 00000000..5b6c9a8f
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-SemiBoldItalic.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-Thin.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Thin.ttf
new file mode 100755
index 00000000..322705a9
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-Thin.ttf differ
diff --git a/src/fonts/JetBrains_Mono/static/JetBrainsMono-ThinItalic.ttf b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ThinItalic.ttf
new file mode 100755
index 00000000..58b40854
Binary files /dev/null and b/src/fonts/JetBrains_Mono/static/JetBrainsMono-ThinItalic.ttf differ
diff --git a/src/graphql/queries.ts b/src/graphql/queries.ts
index e647c73d..f2bf0591 100644
--- a/src/graphql/queries.ts
+++ b/src/graphql/queries.ts
@@ -196,3 +196,61 @@ export const userPositionsQuery = `
}
${marketFragment}
`;
+
+export const marketDetailQuery = `
+ query getMarketDetail($uniqueKey: String!, $chainId: Int) {
+ marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {
+ ...MarketFields
+ }
+ }
+ ${marketFragment}
+`;
+
+export const marketHistoricalDataQuery = `
+ query getMarketHistoricalData($uniqueKey: String!, $options: TimeseriesOptions!, $chainId: Int) {
+ marketByUniqueKey(uniqueKey: $uniqueKey, chainId: $chainId) {
+ historicalState {
+ supplyApy(options: $options) {
+ x
+ y
+ }
+ borrowApy(options: $options) {
+ x
+ y
+ }
+ supplyAssetsUsd(options: $options) {
+ x
+ y
+ }
+ borrowAssetsUsd(options: $options) {
+ x
+ y
+ }
+ supplyAssets(options: $options) {
+ x
+ y
+ }
+ borrowAssets(options: $options) {
+ x
+ y
+ }
+ liquidityAssets(options: $options) {
+ x
+ y
+ }
+ liquidityAssetsUsd(options: $options) {
+ x
+ y
+ }
+ utilization(options: $options) {
+ x
+ y
+ }
+ rateAtUTarget(options: $options) {
+ x
+ y
+ }
+ }
+ }
+ }
+`;
diff --git a/src/hooks/useMarket.ts b/src/hooks/useMarket.ts
new file mode 100644
index 00000000..4c614d00
--- /dev/null
+++ b/src/hooks/useMarket.ts
@@ -0,0 +1,125 @@
+import { useQuery } from '@tanstack/react-query';
+import { getRewardPer1000USD } from '@/utils/morpho';
+import { SupportedNetworks } from '@/utils/networks';
+import { MORPHOTokenAddress } from '@/utils/tokens';
+import { getMarketWarningsWithDetail } from '@/utils/warnings';
+import { marketDetailQuery, marketHistoricalDataQuery } from '../graphql/queries';
+import { MarketDetail, TimeseriesOptions, Market } from '../utils/types';
+
+type GraphQLResponse = {
+ data: {
+ marketByUniqueKey: MarketDetail;
+ };
+ errors?: { message: string }[];
+};
+
+const graphqlFetcher = async (
+ query: string,
+ variables: Record,
+): Promise => {
+ const response = await fetch('https://blue-api.morpho.org/graphql', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ query, variables }),
+ });
+
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+
+ const result = (await response.json()) as GraphQLResponse;
+
+ if (result.errors) {
+ throw new Error(result.errors[0].message);
+ }
+
+ return result;
+};
+
+const processMarketData = (market: Market): MarketDetail => {
+ const entry = market.state.rewards.find(
+ (reward) => reward.asset.address.toLowerCase() === MORPHOTokenAddress?.toLowerCase(),
+ );
+
+ const warningsWithDetail = getMarketWarningsWithDetail(market);
+
+ let rewardPer1000USD: string | undefined;
+ if (entry) {
+ const supplyAssetUSD = Number(market.state.supplyAssetsUsd);
+ rewardPer1000USD = getRewardPer1000USD(entry.yearlySupplyTokens, supplyAssetUSD);
+ }
+
+ return {
+ ...market,
+ rewardPer1000USD,
+ warningsWithDetail,
+ isProtectedByLiquidationBots: false, // NOT needed for now, might implement later
+ historicalState: {
+ supplyApy: [],
+ borrowApy: [],
+ supplyAssetsUsd: [],
+ borrowAssetsUsd: [],
+ rateAtUTarget: [],
+ utilization: [],
+ supplyAssets: [],
+ borrowAssets: [],
+ liquidityAssetsUsd: [],
+ liquidityAssets: [],
+ },
+ };
+};
+
+export const useMarket = (uniqueKey: string, network: SupportedNetworks) => {
+ return useQuery({
+ queryKey: ['market', uniqueKey, network],
+ queryFn: async () => {
+ const response = await graphqlFetcher(marketDetailQuery, { uniqueKey, chainId: network });
+ return processMarketData(response.data.marketByUniqueKey);
+ },
+ });
+};
+
+export const useMarketHistoricalData = (
+ uniqueKey: string,
+ network: SupportedNetworks,
+ rateOptions: TimeseriesOptions,
+ volumeOptions: TimeseriesOptions,
+) => {
+ const fetchHistoricalData = async (options: TimeseriesOptions) => {
+ const response = await graphqlFetcher(marketHistoricalDataQuery, {
+ uniqueKey,
+ options,
+ chainId: network,
+ });
+ return response.data.marketByUniqueKey.historicalState;
+ };
+
+ const rateQuery = useQuery({
+ queryKey: ['marketHistoricalRates', uniqueKey, network, rateOptions],
+ queryFn: async () => fetchHistoricalData(rateOptions),
+ });
+
+ const volumeQuery = useQuery({
+ queryKey: ['marketHistoricalVolumes', uniqueKey, network, volumeOptions],
+ queryFn: async () => fetchHistoricalData(volumeOptions),
+ });
+
+ return {
+ data: {
+ rates: rateQuery.data,
+ volumes: volumeQuery.data,
+ },
+ isLoading: {
+ rates: rateQuery.isLoading,
+ volumes: volumeQuery.isLoading,
+ },
+ error: {
+ rates: rateQuery.error,
+ volumes: volumeQuery.error,
+ },
+ refetch: {
+ rates: rateQuery.refetch,
+ volumes: volumeQuery.refetch,
+ },
+ };
+};
diff --git a/src/utils/balance.ts b/src/utils/balance.ts
index 9cf01aeb..30a7274e 100644
--- a/src/utils/balance.ts
+++ b/src/utils/balance.ts
@@ -22,15 +22,26 @@ export const formatBalance = (value: bigint | string, decimals: number) => {
return Number(value) / 10 ** decimals;
};
-export function formatReadable(num: number): string {
- if (Math.abs(num) >= 1_000_000_000) {
- return (num / 1_000_000_000).toFixed(2) + 'B';
- } else if (Math.abs(num) >= 1_000_000) {
- return (num / 1_000_000).toFixed(2) + 'M';
- } else if (Math.abs(num) >= 1_000) {
- return (num / 1_000).toFixed(2) + 'K';
- } else {
- return num.toFixed(2);
+export function formatReadable(num: number | string): string {
+ if (typeof num === 'string') {
+ const parsed = parseFloat(num);
+ if (isNaN(parsed)) return num;
+ num = parsed;
+ }
+
+ try {
+ if (Math.abs(num) >= 1_000_000_000) {
+ return (num / 1_000_000_000).toFixed(2) + 'B';
+ } else if (Math.abs(num) >= 1_000_000) {
+ return (num / 1_000_000).toFixed(2) + 'M';
+ } else if (Math.abs(num) >= 1_000) {
+ return (num / 1_000).toFixed(2) + 'K';
+ } else {
+ return num.toFixed(2);
+ }
+ } catch (e) {
+ console.log('Error formatting number', e, typeof num);
+ return num.toString();
}
}
diff --git a/src/utils/types.ts b/src/utils/types.ts
index 755d76f9..021b7a97 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -278,3 +278,39 @@ export type Market = {
data: MorphoChainlinkOracleData;
};
};
+
+export type TimeseriesDataPoint = {
+ x: number;
+ y: number;
+};
+
+export type TimeseriesOptions = {
+ startTimestamp: number;
+ endTimestamp: number;
+ interval: 'MINUTE' | 'HALF_HOUR' | 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'QUARTER' | 'YEAR' | 'ALL';
+};
+
+type MarketRates = {
+ supplyApy: TimeseriesDataPoint[];
+ borrowApy: TimeseriesDataPoint[];
+ rateAtUTarget: TimeseriesDataPoint[];
+ utilization: TimeseriesDataPoint[];
+};
+
+type MarketVolumes = {
+ supplyAssetsUsd: TimeseriesDataPoint[];
+ borrowAssetsUsd: TimeseriesDataPoint[];
+ liquidityAssetsUsd: TimeseriesDataPoint[];
+ supplyAssets: TimeseriesDataPoint[];
+ borrowAssets: TimeseriesDataPoint[];
+ liquidityAssets: TimeseriesDataPoint[];
+};
+
+export type MarketDetail = Market & {
+ historicalState: MarketRates & MarketVolumes;
+};
+
+export type MarketHistoricalData = {
+ rates: MarketRates;
+ volumes: MarketVolumes;
+};
diff --git a/yarn.lock b/yarn.lock
index f17f0f5e..abd89802 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1463,6 +1463,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7":
+ version: 7.26.0
+ resolution: "@babel/runtime@npm:7.26.0"
+ dependencies:
+ regenerator-runtime: "npm:^0.14.0"
+ checksum: 10c0/12c01357e0345f89f4f7e8c0e81921f2a3e3e101f06e8eaa18a382b517376520cd2fa8c237726eb094dab25532855df28a7baaf1c26342b52782f6936b07c287
+ languageName: node
+ linkType: hard
+
"@babel/template@npm:^7.24.7, @babel/template@npm:^7.25.0, @babel/template@npm:^7.3.3":
version: 7.25.0
resolution: "@babel/template@npm:7.25.0"
@@ -7716,6 +7725,75 @@ __metadata:
languageName: node
linkType: hard
+"@types/d3-array@npm:^3.0.3":
+ version: 3.2.1
+ resolution: "@types/d3-array@npm:3.2.1"
+ checksum: 10c0/38bf2c778451f4b79ec81a2288cb4312fe3d6449ecdf562970cc339b60f280f31c93a024c7ff512607795e79d3beb0cbda123bb07010167bce32927f71364bca
+ languageName: node
+ linkType: hard
+
+"@types/d3-color@npm:*":
+ version: 3.1.3
+ resolution: "@types/d3-color@npm:3.1.3"
+ checksum: 10c0/65eb0487de606eb5ad81735a9a5b3142d30bc5ea801ed9b14b77cb14c9b909f718c059f13af341264ee189acf171508053342142bdf99338667cea26a2d8d6ae
+ languageName: node
+ linkType: hard
+
+"@types/d3-ease@npm:^3.0.0":
+ version: 3.0.2
+ resolution: "@types/d3-ease@npm:3.0.2"
+ checksum: 10c0/aff5a1e572a937ee9bff6465225d7ba27d5e0c976bd9eacdac2e6f10700a7cb0c9ea2597aff6b43a6ed850a3210030870238894a77ec73e309b4a9d0333f099c
+ languageName: node
+ linkType: hard
+
+"@types/d3-interpolate@npm:^3.0.1":
+ version: 3.0.4
+ resolution: "@types/d3-interpolate@npm:3.0.4"
+ dependencies:
+ "@types/d3-color": "npm:*"
+ checksum: 10c0/066ebb8da570b518dd332df6b12ae3b1eaa0a7f4f0c702e3c57f812cf529cc3500ec2aac8dc094f31897790346c6b1ebd8cd7a077176727f4860c2b181a65ca4
+ languageName: node
+ linkType: hard
+
+"@types/d3-path@npm:*":
+ version: 3.1.0
+ resolution: "@types/d3-path@npm:3.1.0"
+ checksum: 10c0/85e8b3aa968a60a5b33198ade06ae7ffedcf9a22d86f24859ff58e014b053ccb7141ec163b78d547bc8215bb12bb54171c666057ab6156912814005b686afb31
+ languageName: node
+ linkType: hard
+
+"@types/d3-scale@npm:^4.0.2":
+ version: 4.0.8
+ resolution: "@types/d3-scale@npm:4.0.8"
+ dependencies:
+ "@types/d3-time": "npm:*"
+ checksum: 10c0/57de90e4016f640b83cb960b7e3a0ab3ed02e720898840ddc5105264ffcfea73336161442fdc91895377c2d2f91904d637282f16852b8535b77e15a761c8e99e
+ languageName: node
+ linkType: hard
+
+"@types/d3-shape@npm:^3.1.0":
+ version: 3.1.6
+ resolution: "@types/d3-shape@npm:3.1.6"
+ dependencies:
+ "@types/d3-path": "npm:*"
+ checksum: 10c0/0625715925d3c7ed3d44ce998b42c993f063c31605b6e4a8046c4be0fe724e2d214fc83e86d04f429a30a6e1f439053e92b0d9e59e1180c3a5327b4a6e79fa0a
+ languageName: node
+ linkType: hard
+
+"@types/d3-time@npm:*, @types/d3-time@npm:^3.0.0":
+ version: 3.0.3
+ resolution: "@types/d3-time@npm:3.0.3"
+ checksum: 10c0/245a8aadca504df27edf730de502e47a68f16ae795c86b5ca35e7afa91c133aa9ef4d08778f8cf1ed2be732f89a4105ba4b437ce2afbdfd17d3d937b6ba5f568
+ languageName: node
+ linkType: hard
+
+"@types/d3-timer@npm:^3.0.0":
+ version: 3.0.2
+ resolution: "@types/d3-timer@npm:3.0.2"
+ checksum: 10c0/c644dd9571fcc62b1aa12c03bcad40571553020feeb5811f1d8a937ac1e65b8a04b759b4873aef610e28b8714ac71c9885a4d6c127a048d95118f7e5b506d9e1
+ languageName: node
+ linkType: hard
+
"@types/debug@npm:^4.0.0, @types/debug@npm:^4.1.7":
version: 4.1.12
resolution: "@types/debug@npm:4.1.12"
@@ -10080,6 +10158,99 @@ __metadata:
languageName: node
linkType: hard
+"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:^3.1.6":
+ version: 3.2.4
+ resolution: "d3-array@npm:3.2.4"
+ dependencies:
+ internmap: "npm:1 - 2"
+ checksum: 10c0/08b95e91130f98c1375db0e0af718f4371ccacef7d5d257727fe74f79a24383e79aba280b9ffae655483ffbbad4fd1dec4ade0119d88c4749f388641c8bf8c50
+ languageName: node
+ linkType: hard
+
+"d3-color@npm:1 - 3":
+ version: 3.1.0
+ resolution: "d3-color@npm:3.1.0"
+ checksum: 10c0/a4e20e1115fa696fce041fbe13fbc80dc4c19150fa72027a7c128ade980bc0eeeba4bcf28c9e21f0bce0e0dbfe7ca5869ef67746541dcfda053e4802ad19783c
+ languageName: node
+ linkType: hard
+
+"d3-ease@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "d3-ease@npm:3.0.1"
+ checksum: 10c0/fec8ef826c0cc35cda3092c6841e07672868b1839fcaf556e19266a3a37e6bc7977d8298c0fcb9885e7799bfdcef7db1baaba9cd4dcf4bc5e952cf78574a88b0
+ languageName: node
+ linkType: hard
+
+"d3-format@npm:1 - 3":
+ version: 3.1.0
+ resolution: "d3-format@npm:3.1.0"
+ checksum: 10c0/049f5c0871ebce9859fc5e2f07f336b3c5bfff52a2540e0bac7e703fce567cd9346f4ad1079dd18d6f1e0eaa0599941c1810898926f10ac21a31fd0a34b4aa75
+ languageName: node
+ linkType: hard
+
+"d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "d3-interpolate@npm:3.0.1"
+ dependencies:
+ d3-color: "npm:1 - 3"
+ checksum: 10c0/19f4b4daa8d733906671afff7767c19488f51a43d251f8b7f484d5d3cfc36c663f0a66c38fe91eee30f40327443d799be17169f55a293a3ba949e84e57a33e6a
+ languageName: node
+ linkType: hard
+
+"d3-path@npm:^3.1.0":
+ version: 3.1.0
+ resolution: "d3-path@npm:3.1.0"
+ checksum: 10c0/dc1d58ec87fa8319bd240cf7689995111a124b141428354e9637aa83059eb12e681f77187e0ada5dedfce346f7e3d1f903467ceb41b379bfd01cd8e31721f5da
+ languageName: node
+ linkType: hard
+
+"d3-scale@npm:^4.0.2":
+ version: 4.0.2
+ resolution: "d3-scale@npm:4.0.2"
+ dependencies:
+ d3-array: "npm:2.10.0 - 3"
+ d3-format: "npm:1 - 3"
+ d3-interpolate: "npm:1.2.0 - 3"
+ d3-time: "npm:2.1.1 - 3"
+ d3-time-format: "npm:2 - 4"
+ checksum: 10c0/65d9ad8c2641aec30ed5673a7410feb187a224d6ca8d1a520d68a7d6eac9d04caedbff4713d1e8545be33eb7fec5739983a7ab1d22d4e5ad35368c6729d362f1
+ languageName: node
+ linkType: hard
+
+"d3-shape@npm:^3.1.0":
+ version: 3.2.0
+ resolution: "d3-shape@npm:3.2.0"
+ dependencies:
+ d3-path: "npm:^3.1.0"
+ checksum: 10c0/f1c9d1f09926daaf6f6193ae3b4c4b5521e81da7d8902d24b38694517c7f527ce3c9a77a9d3a5722ad1e3ff355860b014557b450023d66a944eabf8cfde37132
+ languageName: node
+ linkType: hard
+
+"d3-time-format@npm:2 - 4":
+ version: 4.1.0
+ resolution: "d3-time-format@npm:4.1.0"
+ dependencies:
+ d3-time: "npm:1 - 3"
+ checksum: 10c0/735e00fb25a7fd5d418fac350018713ae394eefddb0d745fab12bbff0517f9cdb5f807c7bbe87bb6eeb06249662f8ea84fec075f7d0cd68609735b2ceb29d206
+ languageName: node
+ linkType: hard
+
+"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:^3.0.0":
+ version: 3.1.0
+ resolution: "d3-time@npm:3.1.0"
+ dependencies:
+ d3-array: "npm:2 - 3"
+ checksum: 10c0/a984f77e1aaeaa182679b46fbf57eceb6ebdb5f67d7578d6f68ef933f8eeb63737c0949991618a8d29472dbf43736c7d7f17c452b2770f8c1271191cba724ca1
+ languageName: node
+ linkType: hard
+
+"d3-timer@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "d3-timer@npm:3.0.1"
+ checksum: 10c0/d4c63cb4bb5461d7038aac561b097cd1c5673969b27cbdd0e87fa48d9300a538b9e6f39b4a7f0e3592ef4f963d858c8a9f0e92754db73116770856f2fc04561a
+ languageName: node
+ linkType: hard
+
"damerau-levenshtein@npm:^1.0.8":
version: 1.0.8
resolution: "damerau-levenshtein@npm:1.0.8"
@@ -10175,6 +10346,13 @@ __metadata:
languageName: node
linkType: hard
+"decimal.js-light@npm:^2.4.1":
+ version: 2.5.1
+ resolution: "decimal.js-light@npm:2.5.1"
+ checksum: 10c0/4fd33f535aac9e5bd832796831b65d9ec7914ad129c7437b3ab991b0c2eaaa5a57e654e6174c4a17f1b3895ea366f0c1ab4955cdcdf7cfdcf3ad5a58b456c020
+ languageName: node
+ linkType: hard
+
"decimal.js@npm:^10.4.2":
version: 10.4.3
resolution: "decimal.js@npm:10.4.3"
@@ -10444,6 +10622,16 @@ __metadata:
languageName: node
linkType: hard
+"dom-helpers@npm:^5.0.1":
+ version: 5.2.1
+ resolution: "dom-helpers@npm:5.2.1"
+ dependencies:
+ "@babel/runtime": "npm:^7.8.7"
+ csstype: "npm:^3.0.2"
+ checksum: 10c0/f735074d66dd759b36b158fa26e9d00c9388ee0e8c9b16af941c38f014a37fc80782de83afefd621681b19ac0501034b4f1c4a3bff5caa1b8667f0212b5e124c
+ languageName: node
+ linkType: hard
+
"domexception@npm:^4.0.0":
version: 4.0.0
resolution: "domexception@npm:4.0.0"
@@ -11499,6 +11687,13 @@ __metadata:
languageName: node
linkType: hard
+"eventemitter3@npm:^4.0.1":
+ version: 4.0.7
+ resolution: "eventemitter3@npm:4.0.7"
+ checksum: 10c0/5f6d97cbcbac47be798e6355e3a7639a84ee1f7d9b199a07017f1d2f1e2fe236004d14fa5dfaeba661f94ea57805385e326236a6debbc7145c8877fbc0297c6b
+ languageName: node
+ linkType: hard
+
"events@npm:3.3.0, events@npm:^3.3.0":
version: 3.3.0
resolution: "events@npm:3.3.0"
@@ -11598,6 +11793,13 @@ __metadata:
languageName: node
linkType: hard
+"fast-equals@npm:^5.0.1":
+ version: 5.0.1
+ resolution: "fast-equals@npm:5.0.1"
+ checksum: 10c0/d7077b8b681036c2840ed9860a3048e44fc268fad2b525b8f25b43458be0c8ad976152eb4b475de9617170423c5b802121ebb61ed6641c3ac035fadaf805c8c0
+ languageName: node
+ linkType: hard
+
"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0, fast-glob@npm:^3.3.1, fast-glob@npm:^3.3.2":
version: 3.3.2
resolution: "fast-glob@npm:3.3.2"
@@ -12706,6 +12908,13 @@ __metadata:
languageName: node
linkType: hard
+"internmap@npm:1 - 2":
+ version: 2.0.3
+ resolution: "internmap@npm:2.0.3"
+ checksum: 10c0/8cedd57f07bbc22501516fbfc70447f0c6812871d471096fad9ea603516eacc2137b633633daf432c029712df0baefd793686388ddf5737e3ea15074b877f7ed
+ languageName: node
+ linkType: hard
+
"intl-messageformat@npm:^10.1.0":
version: 10.5.14
resolution: "intl-messageformat@npm:10.5.14"
@@ -15102,6 +15311,7 @@ __metadata:
react-spinners: "npm:^0.14.1"
react-table: "npm:^7.8.0"
react-toastify: "npm:^10.0.5"
+ recharts: "npm:^2.13.0"
rehype-pretty-code: "npm:0.12.3"
rehype-stringify: "npm:^10.0.0"
remark-parse: "npm:^11.0.0"
@@ -16309,7 +16519,7 @@ __metadata:
languageName: node
linkType: hard
-"prop-types@npm:^15.8.1":
+"prop-types@npm:^15.6.2, prop-types@npm:^15.8.1":
version: 15.8.1
resolution: "prop-types@npm:15.8.1"
dependencies:
@@ -16495,7 +16705,7 @@ __metadata:
languageName: node
linkType: hard
-"react-is@npm:^18.0.0":
+"react-is@npm:^18.0.0, react-is@npm:^18.3.1":
version: 18.3.1
resolution: "react-is@npm:18.3.1"
checksum: 10c0/f2f1e60010c683479e74c63f96b09fb41603527cd131a9959e2aee1e5a8b0caf270b365e5ca77d4a6b18aae659b60a86150bb3979073528877029b35aecd2072
@@ -16569,6 +16779,20 @@ __metadata:
languageName: node
linkType: hard
+"react-smooth@npm:^4.0.0":
+ version: 4.0.1
+ resolution: "react-smooth@npm:4.0.1"
+ dependencies:
+ fast-equals: "npm:^5.0.1"
+ prop-types: "npm:^15.8.1"
+ react-transition-group: "npm:^4.4.5"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+ checksum: 10c0/5c19a2c147798c3de1329d442b1a371139c01113cc108c38c201b63502c329f943ede505c44089d26a6563eaa72a67b845d538d956f34a389b37fd3961308834
+ languageName: node
+ linkType: hard
+
"react-spinners@npm:^0.14.1":
version: 0.14.1
resolution: "react-spinners@npm:0.14.1"
@@ -16630,6 +16854,21 @@ __metadata:
languageName: node
linkType: hard
+"react-transition-group@npm:^4.4.5":
+ version: 4.4.5
+ resolution: "react-transition-group@npm:4.4.5"
+ dependencies:
+ "@babel/runtime": "npm:^7.5.5"
+ dom-helpers: "npm:^5.0.1"
+ loose-envify: "npm:^1.4.0"
+ prop-types: "npm:^15.6.2"
+ peerDependencies:
+ react: ">=16.6.0"
+ react-dom: ">=16.6.0"
+ checksum: 10c0/2ba754ba748faefa15f87c96dfa700d5525054a0141de8c75763aae6734af0740e77e11261a1e8f4ffc08fd9ab78510122e05c21c2d79066c38bb6861a886c82
+ languageName: node
+ linkType: hard
+
"react@npm:^18":
version: 18.3.1
resolution: "react@npm:18.3.1"
@@ -16703,6 +16942,34 @@ __metadata:
languageName: node
linkType: hard
+"recharts-scale@npm:^0.4.4":
+ version: 0.4.5
+ resolution: "recharts-scale@npm:0.4.5"
+ dependencies:
+ decimal.js-light: "npm:^2.4.1"
+ checksum: 10c0/64ce1fc4ebe62001787bf4dc4cbb779452d33831619309c71c50277c58e8968ffe98941562d9d0d5ffdb02588ebd62f4fe6548fa826110fd458db9c3cc6dadc1
+ languageName: node
+ linkType: hard
+
+"recharts@npm:^2.13.0":
+ version: 2.13.0
+ resolution: "recharts@npm:2.13.0"
+ dependencies:
+ clsx: "npm:^2.0.0"
+ eventemitter3: "npm:^4.0.1"
+ lodash: "npm:^4.17.21"
+ react-is: "npm:^18.3.1"
+ react-smooth: "npm:^4.0.0"
+ recharts-scale: "npm:^0.4.4"
+ tiny-invariant: "npm:^1.3.1"
+ victory-vendor: "npm:^36.6.8"
+ peerDependencies:
+ react: ^16.0.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0
+ checksum: 10c0/40fd9dbacdbb8f0828029f0daaca8a846eada7e017bfdae2790910b38a8ee0f3a9e235f84927d0554da0f0ed46f1f167e84b59f6dc5831113dac0a7763f7d057
+ languageName: node
+ linkType: hard
+
"redent@npm:^3.0.0":
version: 3.0.0
resolution: "redent@npm:3.0.0"
@@ -18270,7 +18537,7 @@ __metadata:
languageName: node
linkType: hard
-"tiny-invariant@npm:^1.1.0":
+"tiny-invariant@npm:^1.1.0, tiny-invariant@npm:^1.3.1":
version: 1.3.3
resolution: "tiny-invariant@npm:1.3.3"
checksum: 10c0/65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a
@@ -19079,6 +19346,28 @@ __metadata:
languageName: node
linkType: hard
+"victory-vendor@npm:^36.6.8":
+ version: 36.9.2
+ resolution: "victory-vendor@npm:36.9.2"
+ dependencies:
+ "@types/d3-array": "npm:^3.0.3"
+ "@types/d3-ease": "npm:^3.0.0"
+ "@types/d3-interpolate": "npm:^3.0.1"
+ "@types/d3-scale": "npm:^4.0.2"
+ "@types/d3-shape": "npm:^3.1.0"
+ "@types/d3-time": "npm:^3.0.0"
+ "@types/d3-timer": "npm:^3.0.0"
+ d3-array: "npm:^3.1.6"
+ d3-ease: "npm:^3.0.1"
+ d3-interpolate: "npm:^3.0.1"
+ d3-scale: "npm:^4.0.2"
+ d3-shape: "npm:^3.1.0"
+ d3-time: "npm:^3.0.0"
+ d3-timer: "npm:^3.0.1"
+ checksum: 10c0/bad36de3bf4d406834743c2e99a8281d786af324d7e84b7f7a2fc02c27a3779034fb0c3c4707d4c8e68683334d924a67100cfa13985235565e83b9877f8e2ffd
+ languageName: node
+ linkType: hard
+
"viem@npm:2.x, viem@npm:^2.1.1":
version: 2.18.7
resolution: "viem@npm:2.18.7"