;
+ }
+ ) => P
+): SimplifiedUseQueryResult => {
+ const isLoading = queries.some((elem) => elem.isLoading);
+ const isAllDataDefined = queries.every((elem) => elem.data);
+ const allData = queries.map((elem) => elem.data) as {
+ [K in keyof Queries]: NonUndefined;
+ };
+ const error = queries.find((elem) => elem.error)?.error;
+ if (!error && !isLoading) {
+ return {
+ isLoading: false,
+ data: combiner(...allData),
+ error: null,
+ };
+ }
+ return {
+ isLoading: isLoading,
+ data: isAllDataDefined ? combiner(...allData) : undefined,
+ error,
+ };
+};
diff --git a/src/hooks/useReserveActionState.tsx b/src/hooks/useReserveActionState.tsx
index b25becce71..b808b8899c 100644
--- a/src/hooks/useReserveActionState.tsx
+++ b/src/hooks/useReserveActionState.tsx
@@ -11,6 +11,7 @@ import { useAssetCaps } from 'src/hooks/useAssetCaps';
import { WalletEmptyInfo } from 'src/modules/dashboard/lists/SupplyAssetsList/WalletEmptyInfo';
import { useRootStore } from 'src/store/root';
import { assetCanBeBorrowedByUser } from 'src/utils/getMaxAmountAvailableToBorrow';
+import { displayGho } from 'src/utils/ghoUtilities';
import { useModalContext } from './useModal';
@@ -29,14 +30,11 @@ export const useReserveActionState = ({
}: ReserveActionStateProps) => {
const { user, eModes } = useAppDataContext();
const { supplyCap, borrowCap, debtCeiling } = useAssetCaps();
- const [currentMarket, currentNetworkConfig, currentChainId, displayGho] = useRootStore(
- (store) => [
- store.currentMarket,
- store.currentNetworkConfig,
- store.currentChainId,
- store.displayGho,
- ]
- );
+ const [currentMarket, currentNetworkConfig, currentChainId] = useRootStore((store) => [
+ store.currentMarket,
+ store.currentNetworkConfig,
+ store.currentChainId,
+ ]);
const { openFaucet } = useModalContext();
const { bridge, name: networkName } = currentNetworkConfig;
diff --git a/src/modules/dashboard/lists/BorrowAssetsList/BorrowAssetsList.tsx b/src/modules/dashboard/lists/BorrowAssetsList/BorrowAssetsList.tsx
index 1c4c320e37..3f62619b74 100644
--- a/src/modules/dashboard/lists/BorrowAssetsList/BorrowAssetsList.tsx
+++ b/src/modules/dashboard/lists/BorrowAssetsList/BorrowAssetsList.tsx
@@ -10,9 +10,8 @@ import { ListHeaderWrapper } from 'src/components/lists/ListHeaderWrapper';
import { Warning } from 'src/components/primitives/Warning';
import { MarketWarning } from 'src/components/transactions/Warnings/MarketWarning';
import { AssetCapsProvider } from 'src/hooks/useAssetCaps';
-import { useRootStore } from 'src/store/root';
import { fetchIconSymbolAndName } from 'src/ui-config/reservePatches';
-import { findAndFilterGhoReserve } from 'src/utils/ghoUtilities';
+import { displayGho, findAndFilterGhoReserve } from 'src/utils/ghoUtilities';
import { GENERAL } from 'src/utils/mixPanelEvents';
import { CapType } from '../../../../components/caps/helper';
@@ -93,7 +92,6 @@ const head = [
export const BorrowAssetsList = () => {
const { currentNetworkConfig, currentMarketData, currentMarket } = useProtocolDataContext();
const { user, reserves, marketReferencePriceInUsd, loading } = useAppDataContext();
- const [displayGho] = useRootStore((store) => [store.displayGho]);
const theme = useTheme();
const downToXSM = useMediaQuery(theme.breakpoints.down('xsm'));
const [sortName, setSortName] = useState('');
diff --git a/src/modules/dashboard/lists/BorrowAssetsList/GhoBorrowAssetsListItem.tsx b/src/modules/dashboard/lists/BorrowAssetsList/GhoBorrowAssetsListItem.tsx
index 4c3a15c553..6685237d13 100644
--- a/src/modules/dashboard/lists/BorrowAssetsList/GhoBorrowAssetsListItem.tsx
+++ b/src/modules/dashboard/lists/BorrowAssetsList/GhoBorrowAssetsListItem.tsx
@@ -11,7 +11,6 @@ import { TokenIcon } from 'src/components/primitives/TokenIcon';
import { useAppDataContext } from 'src/hooks/app-data-provider/useAppDataProvider';
import { useModalContext } from 'src/hooks/useModal';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
-import { useRootStore } from 'src/store/root';
import { CustomMarket } from 'src/ui-config/marketsConfig';
import { DASHBOARD_LIST_COLUMN_WIDTHS } from 'src/utils/dashboardSortUtils';
import { getMaxGhoMintAmount } from 'src/utils/getMaxAmountAvailableToBorrow';
@@ -35,8 +34,7 @@ export const GhoBorrowAssetsListItem = ({
const { openBorrow } = useModalContext();
const { user } = useAppDataContext();
const { currentMarket } = useProtocolDataContext();
- const { ghoReserveData, ghoUserData, ghoLoadingData } = useAppDataContext();
- const { ghoUserDataFetched } = useRootStore();
+ const { ghoReserveData, ghoUserData, ghoUserLoadingData, ghoLoadingData } = useAppDataContext();
const theme = useTheme();
const downToXSM = useMediaQuery(theme.breakpoints.down('xsm'));
@@ -61,7 +59,7 @@ export const GhoBorrowAssetsListItem = ({
ghoUserData.userGhoAvailableToBorrowAtDiscount,
ghoReserveData.ghoBorrowAPYWithMaxDiscount
);
- const ghoApyRange: [number, number] | undefined = ghoUserDataFetched
+ const ghoApyRange: [number, number] | undefined = !ghoUserLoadingData
? [
ghoUserData.userGhoAvailableToBorrowAtDiscount === 0
? ghoReserveData.ghoBorrowAPYWithMaxDiscount
@@ -80,7 +78,7 @@ export const GhoBorrowAssetsListItem = ({
borrowButtonDisable,
userDiscountTokenBalance: ghoUserData.userDiscountTokenBalance,
ghoApyRange,
- ghoUserDataFetched,
+ ghoUserDataFetched: !ghoUserLoadingData,
userBorrowApyAfterNewBorrow,
ghoLoadingData,
onBorrowClick: () => openBorrow(underlyingAsset, currentMarket, name, 'dashboard'),
diff --git a/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItemWrapper.tsx b/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItemWrapper.tsx
index 16d88ff008..402d15730a 100644
--- a/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItemWrapper.tsx
+++ b/src/modules/dashboard/lists/BorrowedPositionsList/BorrowedPositionsListItemWrapper.tsx
@@ -1,13 +1,12 @@
import { AssetCapsProvider } from 'src/hooks/useAssetCaps';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
-import { useRootStore } from 'src/store/root';
import { DashboardReserve } from 'src/utils/dashboardSortUtils';
+import { displayGho } from 'src/utils/ghoUtilities';
import { BorrowedPositionsListItem } from './BorrowedPositionsListItem';
import { GhoBorrowedPositionsListItem } from './GhoBorrowedPositionsListItem';
export const BorrowedPositionsListItemWrapper = ({ item }: { item: DashboardReserve }) => {
- const [displayGho] = useRootStore((store) => [store.displayGho]);
const { currentMarket } = useProtocolDataContext();
return (
diff --git a/src/modules/dashboard/lists/BorrowedPositionsList/GhoBorrowedPositionsListItem.tsx b/src/modules/dashboard/lists/BorrowedPositionsList/GhoBorrowedPositionsListItem.tsx
index 35f8b47963..3fe1ab4413 100644
--- a/src/modules/dashboard/lists/BorrowedPositionsList/GhoBorrowedPositionsListItem.tsx
+++ b/src/modules/dashboard/lists/BorrowedPositionsList/GhoBorrowedPositionsListItem.tsx
@@ -7,12 +7,13 @@ import { GhoIncentivesCard } from 'src/components/incentives/GhoIncentivesCard';
import { FixedAPYTooltipText } from 'src/components/infoTooltips/FixedAPYTooltip';
import { ROUTES } from 'src/components/primitives/Link';
import { Row } from 'src/components/primitives/Row';
+import { useGhoPoolReserve } from 'src/hooks/pool/useGhoPoolReserve';
+import { useUserGhoPoolReserve } from 'src/hooks/pool/useUserGhoPoolReserve';
import { useModalContext } from 'src/hooks/useModal';
-import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
import { useRootStore } from 'src/store/root';
import { CustomMarket } from 'src/ui-config/marketsConfig';
import { getMaxGhoMintAmount } from 'src/utils/getMaxAmountAvailableToBorrow';
-import { weightedAverageAPY } from 'src/utils/ghoUtilities';
+import { ghoUserQualifiesForDiscount, weightedAverageAPY } from 'src/utils/ghoUtilities';
import { isFeatureEnabled } from 'src/utils/marketsAndNetworksConfig';
import { ListColumn } from '../../../../components/lists/ListColumn';
@@ -32,12 +33,12 @@ export const GhoBorrowedPositionsListItem = ({
borrowRateMode,
}: ComputedUserReserveData & { borrowRateMode: InterestRate }) => {
const { openBorrow, openRepay, openDebtSwitch } = useModalContext();
- const { currentMarket, currentMarketData } = useProtocolDataContext();
- const { ghoLoadingData, ghoReserveData, ghoUserData, user } = useAppDataContext();
- const [ghoUserDataFetched, ghoUserQualifiesForDiscount] = useRootStore((store) => [
- store.ghoUserDataFetched,
- store.ghoUserQualifiesForDiscount,
- ]);
+ const currentMarket = useRootStore((store) => store.currentMarket);
+ const currentMarketData = useRootStore((store) => store.currentMarketData);
+ const { ghoLoadingData, ghoReserveData, ghoUserData, ghoUserLoadingData, user } =
+ useAppDataContext();
+ const { data: _ghoUserData } = useUserGhoPoolReserve(currentMarketData);
+ const { data: _ghoReserveData } = useGhoPoolReserve(currentMarketData);
const theme = useTheme();
const downToXSM = useMediaQuery(theme.breakpoints.down('xsm'));
@@ -52,7 +53,10 @@ export const GhoBorrowedPositionsListItem = ({
ghoReserveData.ghoBorrowAPYWithMaxDiscount
);
- const hasDiscount = ghoUserQualifiesForDiscount();
+ const hasDiscount =
+ _ghoUserData && _ghoReserveData
+ ? ghoUserQualifiesForDiscount(_ghoReserveData, _ghoUserData)
+ : false;
const { isActive, isFrozen, isPaused, borrowingEnabled } = reserve;
const maxAmountUserCanMint = Number(getMaxGhoMintAmount(user, reserve));
@@ -67,7 +71,7 @@ export const GhoBorrowedPositionsListItem = ({
userGhoBorrowBalance: ghoUserData.userGhoBorrowBalance,
hasDiscount,
ghoLoadingData,
- ghoUserDataFetched,
+ ghoUserDataFetched: !ghoUserLoadingData,
borrowRateAfterDiscount,
currentMarket,
userDiscountTokenBalance: ghoUserData.userDiscountTokenBalance,
diff --git a/src/modules/dashboard/lists/SupplyAssetsList/SupplyAssetsList.tsx b/src/modules/dashboard/lists/SupplyAssetsList/SupplyAssetsList.tsx
index 5cf330f60b..1699413633 100644
--- a/src/modules/dashboard/lists/SupplyAssetsList/SupplyAssetsList.tsx
+++ b/src/modules/dashboard/lists/SupplyAssetsList/SupplyAssetsList.tsx
@@ -12,6 +12,7 @@ import { MarketWarning } from 'src/components/transactions/Warnings/MarketWarnin
import { AssetCapsProvider } from 'src/hooks/useAssetCaps';
import { useRootStore } from 'src/store/root';
import { fetchIconSymbolAndName } from 'src/ui-config/reservePatches';
+import { displayGho } from 'src/utils/ghoUtilities';
import { ListWrapper } from '../../../../components/lists/ListWrapper';
import { Link, ROUTES } from '../../../../components/primitives/Link';
@@ -54,7 +55,6 @@ export const SupplyAssetsList = () => {
loading: loadingReserves,
} = useAppDataContext();
const { walletBalances, loading } = useWalletBalances(currentMarketData);
- const [displayGho] = useRootStore((store) => [store.displayGho]);
const theme = useTheme();
const downToXSM = useMediaQuery(theme.breakpoints.down('xsm'));
diff --git a/src/modules/reserve-overview/ReserveActions.tsx b/src/modules/reserve-overview/ReserveActions.tsx
index 91551904fb..e2b92ab673 100644
--- a/src/modules/reserve-overview/ReserveActions.tsx
+++ b/src/modules/reserve-overview/ReserveActions.tsx
@@ -36,6 +36,7 @@ import {
getMaxGhoMintAmount,
} from 'src/utils/getMaxAmountAvailableToBorrow';
import { getMaxAmountAvailableToSupply } from 'src/utils/getMaxAmountAvailableToSupply';
+import { displayGho } from 'src/utils/ghoUtilities';
import { GENERAL } from 'src/utils/mixPanelEvents';
import { amountToUsd } from 'src/utils/utils';
@@ -77,9 +78,8 @@ export const ReserveActions = ({ reserve }: ReserveActionsProps) => {
} = useAppDataContext();
const { walletBalances, loading: loadingWalletBalance } = useWalletBalances(currentMarketData);
- const [minRemainingBaseTokenBalance, displayGho] = useRootStore((store) => [
+ const [minRemainingBaseTokenBalance] = useRootStore((store) => [
store.poolComputed.minRemainingBaseTokenBalance,
- store.displayGho,
]);
const { baseAssetSymbol } = currentNetworkConfig;
let balance = walletBalances[reserve.underlyingAsset];
diff --git a/src/modules/reserve-overview/ReserveConfigurationWrapper.tsx b/src/modules/reserve-overview/ReserveConfigurationWrapper.tsx
index 469f100f1a..d8e0c7a269 100644
--- a/src/modules/reserve-overview/ReserveConfigurationWrapper.tsx
+++ b/src/modules/reserve-overview/ReserveConfigurationWrapper.tsx
@@ -3,7 +3,7 @@ import { Box, Paper, Typography, useMediaQuery, useTheme } from '@mui/material';
import dynamic from 'next/dynamic';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
-import { useRootStore } from 'src/store/root';
+import { displayGho } from 'src/utils/ghoUtilities';
type ReserveConfigurationProps = {
reserve: ComputedReserveData;
@@ -19,7 +19,6 @@ const ReserveConfiguration = dynamic(() =>
export const ReserveConfigurationWrapper: React.FC = ({ reserve }) => {
const { currentMarket } = useProtocolDataContext();
- const [displayGho] = useRootStore((store) => [store.displayGho]);
const { breakpoints } = useTheme();
const downToXsm = useMediaQuery(breakpoints.down('xsm'));
const isGho = displayGho({ symbol: reserve.symbol, currentMarket });
diff --git a/src/modules/reserve-overview/ReserveTopDetailsWrapper.tsx b/src/modules/reserve-overview/ReserveTopDetailsWrapper.tsx
index f54eba9e3c..e6a9adba16 100644
--- a/src/modules/reserve-overview/ReserveTopDetailsWrapper.tsx
+++ b/src/modules/reserve-overview/ReserveTopDetailsWrapper.tsx
@@ -14,7 +14,7 @@ import { useRouter } from 'next/router';
import { getMarketInfoById, MarketLogo } from 'src/components/MarketSwitcher';
import { useProtocolDataContext } from 'src/hooks/useProtocolDataContext';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
-import { useRootStore } from 'src/store/root';
+import { displayGho } from 'src/utils/ghoUtilities';
import { TopInfoPanel } from '../../components/TopInfoPanel/TopInfoPanel';
import { TopInfoPanelItem } from '../../components/TopInfoPanel/TopInfoPanelItem';
@@ -37,7 +37,6 @@ export const ReserveTopDetailsWrapper = ({ underlyingAsset }: ReserveTopDetailsP
const { currentMarket, currentChainId } = useProtocolDataContext();
const { market, network } = getMarketInfoById(currentMarket);
const { addERC20Token, switchNetwork, chainId: connectedChainId, connected } = useWeb3Context();
- const [displayGho] = useRootStore((store) => [store.displayGho]);
const theme = useTheme();
const downToSM = useMediaQuery(theme.breakpoints.down('sm'));
diff --git a/src/services/UiGhoService.ts b/src/services/UiGhoService.ts
new file mode 100644
index 0000000000..79a2edba76
--- /dev/null
+++ b/src/services/UiGhoService.ts
@@ -0,0 +1,34 @@
+import { GhoService } from '@aave/contract-helpers';
+import { Provider } from '@ethersproject/providers';
+import { MarketDataType } from 'src/ui-config/marketsConfig';
+import { GHO_SUPPORTED_MARKETS } from 'src/utils/ghoUtilities';
+import invariant from 'tiny-invariant';
+
+export class UiGhoService {
+ constructor(private readonly getProvider: (chainId: number) => Provider) {}
+
+ private getUiGhoProvider(marketData: MarketDataType) {
+ const provider = this.getProvider(marketData.chainId);
+ const isGhoSupportedMarket = GHO_SUPPORTED_MARKETS.includes(marketData.market);
+ invariant(isGhoSupportedMarket, 'Gho is not supported in this market');
+ const { GHO_TOKEN_ADDRESS: ghoTokenAddress, GHO_UI_DATA_PROVIDER: uiGhoDataProviderAddress } =
+ marketData.addresses;
+ invariant(
+ ghoTokenAddress && uiGhoDataProviderAddress,
+ 'Gho token address or UI Gho data provider address not found for this market'
+ );
+ return new GhoService({
+ provider,
+ uiGhoDataProviderAddress: uiGhoDataProviderAddress,
+ });
+ }
+
+ async getGhoReserveData(marketData: MarketDataType) {
+ const uiGhoProvider = this.getUiGhoProvider(marketData);
+ return uiGhoProvider.getGhoReserveData();
+ }
+ async getGhoUserData(marketData: MarketDataType, user: string) {
+ const uiGhoProvider = this.getUiGhoProvider(marketData);
+ return uiGhoProvider.getGhoUserData(user);
+ }
+}
diff --git a/src/store/ghoSlice.ts b/src/store/ghoSlice.ts
deleted file mode 100644
index 627330aca5..0000000000
--- a/src/store/ghoSlice.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-import { GhoService } from '@aave/contract-helpers';
-import { GhoReserveData, GhoUserData, normalize } from '@aave/math-utils';
-import { GHO_SUPPORTED_MARKETS } from 'src/utils/ghoUtilities';
-import { getProvider } from 'src/utils/marketsAndNetworksConfig';
-import { StateCreator } from 'zustand';
-
-import { RootStore } from './root';
-
-interface GhoMarketConfig {
- ghoTokenAddress: string;
- uiGhoDataProviderAddress: string;
-}
-
-interface GhoUtilMintingAvailableParams {
- symbol: string;
- currentMarket: string;
-}
-
-export interface GhoSlice {
- ghoReserveData: GhoReserveData;
- ghoUserData: GhoUserData;
- ghoReserveDataFetched: boolean;
- ghoUserDataFetched: boolean;
- ghoUserQualifiesForDiscount: (futureBorrowAmount?: string) => boolean;
- ghoMarketConfig: () => GhoMarketConfig | undefined;
- refreshGhoData: () => Promise;
- displayGho: ({ symbol, currentMarket }: GhoUtilMintingAvailableParams) => boolean;
-}
-
-export const createGhoSlice: StateCreator<
- RootStore,
- [['zustand/subscribeWithSelector', never], ['zustand/devtools', never]],
- [],
- GhoSlice
-> = (set, get) => {
- return {
- ghoReserveData: {
- ghoBaseVariableBorrowRate: '0',
- ghoDiscountedPerToken: '0',
- ghoDiscountRate: '0',
- ghoMinDebtTokenBalanceForDiscount: '0',
- ghoMinDiscountTokenBalanceForDiscount: '0',
- ghoReserveLastUpdateTimestamp: '0',
- ghoCurrentBorrowIndex: '0',
- aaveFacilitatorBucketLevel: '0',
- aaveFacilitatorBucketMaxCapacity: '0',
- },
- ghoUserData: {
- userGhoDiscountPercent: '0',
- userDiscountTokenBalance: '0',
- userPreviousGhoBorrowIndex: '0',
- userGhoScaledBorrowBalance: '0',
- },
- ghoReserveDataFetched: false,
- ghoUserDataFetched: false,
- displayGho: ({ symbol, currentMarket }: GhoUtilMintingAvailableParams): boolean => {
- return symbol === 'GHO' && GHO_SUPPORTED_MARKETS.includes(currentMarket);
- },
- ghoUserQualifiesForDiscount: (futureBorrowAmount = '0') => {
- const ghoReserveDataFetched = get().ghoReserveDataFetched;
- const ghoUserDataFetched = get().ghoUserDataFetched;
-
- if (!ghoReserveDataFetched || !ghoUserDataFetched) return false;
-
- const ghoReserveData = get().ghoReserveData;
- const ghoUserData = get().ghoUserData;
-
- const borrowBalance = Number(normalize(ghoUserData.userGhoScaledBorrowBalance, 18));
- const minBorrowBalanceForDiscount = Number(
- normalize(ghoReserveData.ghoMinDebtTokenBalanceForDiscount, 18)
- );
-
- const stkAaveBalance = Number(normalize(ghoUserData.userDiscountTokenBalance, 18));
- const minStkAaveBalanceForDiscount = Number(
- normalize(ghoReserveData.ghoMinDiscountTokenBalanceForDiscount, 18)
- );
-
- return (
- borrowBalance + Number(futureBorrowAmount) >= minBorrowBalanceForDiscount &&
- stkAaveBalance >= minStkAaveBalanceForDiscount
- );
- },
- ghoMarketConfig: () => {
- const market = get().currentMarket;
- if (!GHO_SUPPORTED_MARKETS.includes(market)) {
- return undefined;
- }
-
- const { GHO_TOKEN_ADDRESS: ghoTokenAddress, GHO_UI_DATA_PROVIDER: uiGhoDataProviderAddress } =
- get().currentMarketData.addresses;
- if (!ghoTokenAddress || !uiGhoDataProviderAddress) {
- return undefined;
- }
-
- return {
- ghoTokenAddress,
- uiGhoDataProviderAddress,
- };
- },
- refreshGhoData: async () => {
- const ghoConfig = get().ghoMarketConfig();
- if (!ghoConfig) return;
-
- const account = get().account;
-
- const ghoService = new GhoService({
- provider: getProvider(get().currentMarketData.chainId),
- uiGhoDataProviderAddress: ghoConfig.uiGhoDataProviderAddress,
- });
-
- if (account) {
- try {
- const [ghoReserveData, ghoUserData] = await Promise.all([
- ghoService.getGhoReserveData(),
- ghoService.getGhoUserData(account),
- ]);
-
- set({
- ghoReserveData: ghoReserveData,
- ghoUserData: ghoUserData,
- ghoReserveDataFetched: true,
- ghoUserDataFetched: true,
- });
- } catch (err) {
- console.log('error', err);
- }
- } else {
- try {
- const ghoReserveData = await ghoService.getGhoReserveData();
-
- set({
- ghoReserveData: ghoReserveData,
- ghoReserveDataFetched: true,
- ghoUserDataFetched: false,
- });
- } catch (err) {
- console.log('error', err);
- }
- }
- },
- };
-};
diff --git a/src/store/root.ts b/src/store/root.ts
index 2a0173b20d..5ddcd2fbca 100644
--- a/src/store/root.ts
+++ b/src/store/root.ts
@@ -4,7 +4,6 @@ import create from 'zustand';
import { devtools, subscribeWithSelector } from 'zustand/middleware';
import { AnalyticsSlice, createAnalyticsSlice } from './analyticsSlice';
-import { createGhoSlice, GhoSlice } from './ghoSlice';
import { createGovernanceSlice, GovernanceSlice } from './governanceSlice';
import { createIncentiveSlice, IncentiveSlice } from './incentiveSlice';
import { createLayoutSlice, LayoutSlice } from './layoutSlice';
@@ -27,7 +26,6 @@ export type RootStore = StakeSlice &
IncentiveSlice &
GovernanceSlice &
V3MigrationSlice &
- GhoSlice &
WalletDomainsSlice &
AnalyticsSlice &
TransactionsSlice &
@@ -44,7 +42,6 @@ export const useRootStore = create()(
...createIncentiveSlice(...args),
...createGovernanceSlice(...args),
...createV3MigrationSlice(...args),
- ...createGhoSlice(...args),
...createWalletDomainsSlice(...args),
...createAnalyticsSlice(...args),
...createTransactionsSlice(...args),
@@ -84,10 +81,6 @@ export const useIncentiveDataSubscription = createSingletonSubscriber(() => {
return useRootStore.getState().refreshIncentiveData();
}, 60000);
-export const useGhoDataSubscription = createSingletonSubscriber(() => {
- return useRootStore.getState().refreshGhoData();
-}, 60000);
-
useRootStore.subscribe(
(state) => state.account,
(account) => {
diff --git a/src/ui-config/SharedDependenciesProvider.tsx b/src/ui-config/SharedDependenciesProvider.tsx
index 952b14d538..491b9034bf 100644
--- a/src/ui-config/SharedDependenciesProvider.tsx
+++ b/src/ui-config/SharedDependenciesProvider.tsx
@@ -4,6 +4,7 @@ import { DelegationTokenService } from 'src/services/DelegationTokenService';
import { GovernanceService } from 'src/services/GovernanceService';
import { GovernanceV3Service } from 'src/services/GovernanceV3Service';
import { StkAbptMigrationService } from 'src/services/StkAbptMigrationService';
+import { UiGhoService } from 'src/services/UiGhoService';
import { UiIncentivesService } from 'src/services/UIIncentivesService';
import { UiPoolService } from 'src/services/UIPoolService';
import { UiStakeDataService } from 'src/services/UiStakeDataService';
@@ -25,6 +26,7 @@ interface SharedDependenciesContext {
approvedAmountService: ApprovedAmountService;
uiIncentivesService: UiIncentivesService;
uiPoolService: UiPoolService;
+ uiGhoService: UiGhoService;
delegationTokenService: DelegationTokenService;
stkAbptMigrationService: StkAbptMigrationService;
}
@@ -59,6 +61,8 @@ export const SharedDependenciesProvider: React.FC = ({ children }) => {
const uiPoolService = new UiPoolService(getProvider);
const uiIncentivesService = new UiIncentivesService(getProvider);
+ const uiGhoService = new UiGhoService(getProvider);
+
return (
{
approvedAmountService,
uiPoolService,
uiIncentivesService,
+ uiGhoService,
delegationTokenService,
stkAbptMigrationService,
}}
diff --git a/src/ui-config/queries.ts b/src/ui-config/queries.ts
index febf35fb58..3d1dee942f 100644
--- a/src/ui-config/queries.ts
+++ b/src/ui-config/queries.ts
@@ -87,6 +87,17 @@ export const queryKeysFactory = {
user: string
) => [...queryKeysFactory.user(user), chainId, amount, srcToken, destToken, 'paraswapRates'],
gasPrices: (chainId: number) => [chainId, 'gasPrices'],
+ ghoReserveData: (marketData: MarketDataType) => [
+ ...queryKeysFactory.gho,
+ ...queryKeysFactory.market(marketData),
+ 'ghoReserveData',
+ ],
+ ghoUserReserveData: (user: string, marketData: MarketDataType) => [
+ ...queryKeysFactory.gho,
+ ...queryKeysFactory.user(user),
+ ...queryKeysFactory.market(marketData),
+ 'ghoUserReserveData',
+ ],
poolApprovedAmount: (user: string, token: string, marketData: MarketDataType) => [
...queryKeysFactory.pool,
...queryKeysFactory.user(user),
diff --git a/src/utils/ghoUtilities.tsx b/src/utils/ghoUtilities.tsx
index 61d5a434be..c189e20410 100644
--- a/src/utils/ghoUtilities.tsx
+++ b/src/utils/ghoUtilities.tsx
@@ -1,3 +1,4 @@
+import { GhoReserveData, GhoUserData, normalize } from '@aave/math-utils';
import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider';
export const GHO_SYMBOL = 'GHO';
@@ -98,3 +99,33 @@ export const findAndFilterGhoReserve = (reserves: A
}
);
};
+
+export const displayGho = ({ symbol, currentMarket }: GhoUtilMintingAvailableParams): boolean => {
+ return symbol === 'GHO' && GHO_SUPPORTED_MARKETS.includes(currentMarket);
+};
+
+interface GhoUtilMintingAvailableParams {
+ symbol: string;
+ currentMarket: string;
+}
+
+export const ghoUserQualifiesForDiscount = (
+ ghoReserveData: GhoReserveData,
+ ghoUserData: GhoUserData,
+ futureBorrowAmount = '0'
+) => {
+ const borrowBalance = Number(normalize(ghoUserData.userGhoScaledBorrowBalance, 18));
+ const minBorrowBalanceForDiscount = Number(
+ normalize(ghoReserveData.ghoMinDebtTokenBalanceForDiscount, 18)
+ );
+
+ const stkAaveBalance = Number(normalize(ghoUserData.userDiscountTokenBalance, 18));
+ const minStkAaveBalanceForDiscount = Number(
+ normalize(ghoReserveData.ghoMinDiscountTokenBalanceForDiscount, 18)
+ );
+
+ return (
+ borrowBalance + Number(futureBorrowAmount) >= minBorrowBalanceForDiscount &&
+ stkAaveBalance >= minStkAaveBalanceForDiscount
+ );
+};
diff --git a/yarn.lock b/yarn.lock
index ffc05ddcb2..5159f792b5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9707,6 +9707,11 @@ messageformat-parser@^4.1.3:
resolved "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-4.1.3.tgz"
integrity sha512-2fU3XDCanRqeOCkn7R5zW5VQHWf+T3hH65SzuqRvjatBK7r4uyFa5mEX+k6F9Bd04LVM5G4/BHBTUJsOdW7uyg==
+micro-memoize@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/micro-memoize/-/micro-memoize-4.1.2.tgz#ce719c1ba1e41592f1cd91c64c5f41dcbf135f36"
+ integrity sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==
+
micromark-core-commonmark@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8"