Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@
},
"dependencies": {
"@aave/contract-helpers": "1.36.1",
"@aave/graphql": "^0.7.0",
"@aave/math-utils": "1.36.1",
"@aave/react": "0.6.1",
"@aave/react": "^0.7.0",
"@amplitude/analytics-browser": "^2.13.0",
"@bgd-labs/aave-address-book": "^4.31.0",
"@cowprotocol/app-data": "^3.1.0",
Expand Down
28 changes: 19 additions & 9 deletions pages/reserve-overview.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import StyledToggleButton from 'src/components/StyledToggleButton';
import StyledToggleButtonGroup from 'src/components/StyledToggleButtonGroup';
import {
ComputedReserveData,
ReserveWithId,
useAppDataContext,
} from 'src/hooks/app-data-provider/useAppDataProvider';
import { AssetCapsProvider } from 'src/hooks/useAssetCaps';
import { AssetCapsProviderSDK } from 'src/hooks/useAssetCapsSDK';
import { MainLayout } from 'src/layouts/MainLayout';
import { ReserveActions } from 'src/modules/reserve-overview/ReserveActions';
import { ReserveConfigurationWrapper } from 'src/modules/reserve-overview/ReserveConfigurationWrapper';
Expand Down Expand Up @@ -44,23 +46,28 @@ const UnStakeModal = dynamic(() =>

export default function ReserveOverview() {
const router = useRouter();
const { reserves } = useAppDataContext();
const { supplyReserves, reserves } = useAppDataContext();
const underlyingAsset = router.query.underlyingAsset as string;

const [mode, setMode] = useState<'overview' | 'actions' | ''>('overview');
const trackEvent = useRootStore((store) => store.trackEvent);

const reserve = reserves.find(
(reserve) => reserve.underlyingAsset === underlyingAsset
) as ComputedReserveData;
//With SDK
const reserve = supplyReserves.find((reserve) => {
return reserve.underlyingToken.address.toLowerCase() === underlyingAsset?.toLowerCase();
}) as ReserveWithId;

//With Reserves
const reserveLegacy = reserves.find((reserve) => {
return reserve.underlyingAsset.toLowerCase() === underlyingAsset?.toLowerCase();
}) as ComputedReserveData;
const [pageEventCalled, setPageEventCalled] = useState(false);

useEffect(() => {
if (!pageEventCalled && reserve && reserve.iconSymbol && underlyingAsset) {
if (!pageEventCalled && reserve && reserve.underlyingToken.symbol && underlyingAsset) {
trackEvent('Page Viewed', {
'Page Name': 'Reserve Overview',
Reserve: reserve.iconSymbol,
Reserve: reserve.underlyingToken.symbol,
Asset: underlyingAsset,
});
setPageEventCalled(true);
Expand All @@ -70,7 +77,7 @@ export default function ReserveOverview() {
const isOverview = mode === 'overview';

return (
<AssetCapsProvider asset={reserve}>
<AssetCapsProviderSDK asset={reserve}>
<ReserveTopDetailsWrapper underlyingAsset={underlyingAsset} />

<ContentContainer>
Expand Down Expand Up @@ -120,11 +127,14 @@ export default function ReserveOverview() {
width: { xs: '100%', lg: '416px' },
}}
>
<ReserveActions reserve={reserve} />
{/* Wrapped in AssetCapsProvider to provide the data using legacy method to avoid braking actions */}
<AssetCapsProvider asset={reserveLegacy}>
<ReserveActions reserve={reserveLegacy} />
</AssetCapsProvider>
</Box>
</Box>
</ContentContainer>
</AssetCapsProvider>
</AssetCapsProviderSDK>
);
}

Expand Down
184 changes: 184 additions & 0 deletions src/hooks/useAssetCapsSDK.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { valueToBigNumber } from '@aave/math-utils';
import { SxProps, Theme } from '@mui/system';
import { createContext, ReactNode, useContext } from 'react';
import { BorrowCapMaxedTooltip } from 'src/components/infoTooltips/BorrowCapMaxedTooltip';
import { DebtCeilingMaxedTooltip } from 'src/components/infoTooltips/DebtCeilingMaxedTooltip';
import { SupplyCapMaxedTooltip } from 'src/components/infoTooltips/SupplyCapMaxedTooltip';
import { BorrowCapWarning } from 'src/components/transactions/Warnings/BorrowCapWarning';
import { DebtCeilingWarning } from 'src/components/transactions/Warnings/DebtCeilingWarning';
import { SupplyCapWarning } from 'src/components/transactions/Warnings/SupplyCapWarning';

import { ReserveWithId } from './app-data-provider/useAppDataProvider';

type WarningDisplayProps = {
supplyCap?: AssetCapData;
borrowCap?: AssetCapData;
debtCeiling?: AssetCapData;
icon?: boolean;
sx?: SxProps<Theme>;
};

export type AssetCapData = {
percentUsed: number;
isMaxed: boolean;
};

export type AssetCapHookData = AssetCapData & {
determineWarningDisplay: (props: WarningDisplayProps) => JSX.Element | null;
displayMaxedTooltip: (props: WarningDisplayProps) => JSX.Element | null;
};

export type AssetCapUsageData = {
reserve: ReserveWithId;
supplyCap: AssetCapHookData;
borrowCap: AssetCapHookData;
debtCeiling: AssetCapHookData;
};

const getAssetCapData = (asset: ReserveWithId): AssetCapUsageData => {
const { supplyCapUsage, supplyCapReached } = getSupplyCapData(asset);
const { borrowCapUsage, borrowCapReached } = getBorrowCapData(asset);
const { debtCeilingUsage, debtCeilingReached } = getDebtCeilingData(asset);
/*
Aggregated Data
*/
const assetCapUsageData: AssetCapUsageData = {
reserve: asset,
supplyCap: {
percentUsed: supplyCapUsage,
isMaxed: supplyCapReached,
// percentUsed: 99.9,
// isMaxed: true,
determineWarningDisplay: ({ supplyCap, icon, ...rest }) =>
supplyCap ? <SupplyCapWarning supplyCap={supplyCap} icon={icon} {...rest} /> : null,
displayMaxedTooltip: ({ supplyCap }) =>
supplyCap ? <SupplyCapMaxedTooltip supplyCap={supplyCap} /> : null,
},
borrowCap: {
percentUsed: borrowCapUsage,
isMaxed: borrowCapReached,
// percentUsed: 98.5,
// isMaxed: false,
determineWarningDisplay: ({ borrowCap, icon, ...rest }) =>
borrowCap ? <BorrowCapWarning borrowCap={borrowCap} icon={icon} {...rest} /> : null,
displayMaxedTooltip: ({ borrowCap }) =>
borrowCap ? <BorrowCapMaxedTooltip borrowCap={borrowCap} /> : null,
},
debtCeiling: {
percentUsed: debtCeilingUsage,
isMaxed: debtCeilingReached,
// percentUsed: 99.994,
// isMaxed: true,
determineWarningDisplay: ({ debtCeiling, icon, ...rest }) =>
debtCeiling ? <DebtCeilingWarning debtCeiling={debtCeiling} icon={icon} {...rest} /> : null,
displayMaxedTooltip: ({ debtCeiling }) =>
debtCeiling ? <DebtCeilingMaxedTooltip debtCeiling={debtCeiling} /> : null,
},
};

return assetCapUsageData;
};

/*
Asset Caps Context
*/
export const AssetCapsSDKContext = createContext({} as AssetCapUsageData);

/*
Asset Caps Provider Component
*/
export const AssetCapsProvider = ({
children,
asset,
}: {
children: ReactNode;
asset: ReserveWithId;
}): JSX.Element | null => {
// Return if no reserve is provided
if (!asset) {
console.warn('<AssetCapsProvider /> was not given a valid reserve asset to parse');
return null;
}

const providerValue = getAssetCapData(asset);

return (
<AssetCapsSDKContext.Provider value={providerValue}>{children}</AssetCapsSDKContext.Provider>
);
};

/*
useAssetCaspsSDKContext hook
*/
export const useAssetCapsSDK = () => {
const context = useContext(AssetCapsSDKContext);

if (context === undefined) {
throw new Error(
'useAssetCaps() can only be used inside of <AssetCapsProvider />, ' +
'please declare it at a higher level.'
);
}

return context;
};

export { AssetCapsProvider as AssetCapsProviderSDK };

/**
* Calculates % of totalLiquidity / supplyCap.
* @param asset ReserveWithId
* @returns { supplyCapUsage: number, supplyCapReached: boolean }
*/
export const getSupplyCapData = (asset: ReserveWithId) => {
const total = valueToBigNumber(asset?.supplyInfo?.total.value ?? '0');
const cap = valueToBigNumber(asset?.supplyInfo?.supplyCap.amount.value ?? '0');

const rawUsage = cap.isZero() ? 0 : total.dividedBy(cap).multipliedBy(100).toNumber();

return {
supplyCapUsage: Number.isFinite(rawUsage) ? rawUsage : 0,
supplyCapReached: asset?.supplyInfo?.supplyCapReached ?? false,
};
};

/**
* Calculates borrow cap usage and % of totalDebt / borrowCap.
* @param asset ReserveWithId
* @returns { borrowCapUsage: number, borrowCapReached: boolean }
*/
export const getBorrowCapData = (asset: ReserveWithId) => {
const totalDebt = valueToBigNumber(asset?.borrowInfo?.total.amount.value ?? '0');
const cap = valueToBigNumber(asset?.borrowInfo?.borrowCap.amount.value ?? '0');

const rawUsage = cap.isZero() ? 0 : totalDebt.dividedBy(cap).multipliedBy(100).toNumber();

const borrowCapReached = asset?.borrowInfo?.borrowCapReached || rawUsage >= 99.99;

return {
borrowCapUsage: Number.isFinite(rawUsage) ? rawUsage : 0,
borrowCapReached: borrowCapReached ?? false,
};
};

/**
* Calculates debt ceiling usage and % of isolationModeTotalDebt / debtCeiling.
* @param asset
* @returns {debtCeilingUsage: number, debtCeilingReached: boolean}
*/
export const getDebtCeilingData = (asset: ReserveWithId) => {
const totalBorrows = valueToBigNumber(
asset?.isolationModeConfig?.totalBorrows.amount.value ?? '0'
);
const debtCeilingCap = valueToBigNumber(
asset?.isolationModeConfig?.debtCeiling.amount.value ?? '0'
);
const rawUsage = debtCeilingCap.isZero()
? 0
: totalBorrows.dividedBy(debtCeilingCap).multipliedBy(100).toNumber();

return {
debtCeilingUsage: Number.isFinite(rawUsage) ? rawUsage : 0,
debtCeilingReached: rawUsage >= 99.99,
};
};
2 changes: 1 addition & 1 deletion src/locales/el/messages.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/locales/en/messages.js

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -2013,10 +2013,6 @@ msgstr "Nothing supplied yet"
msgid "Voting"
msgstr "Voting"

#: src/modules/reserve-overview/SupplyInfo.tsx
msgid "Unbacked"
msgstr "Unbacked"

#: src/components/infoTooltips/EModeTooltip.tsx
msgid "E-Mode increases your LTV for a selected category of assets up to<0/>. <1>Learn more</1>"
msgstr "E-Mode increases your LTV for a selected category of assets up to<0/>. <1>Learn more</1>"
Expand Down
2 changes: 1 addition & 1 deletion src/locales/es/messages.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/locales/fr/messages.js

Large diffs are not rendered by default.

Loading