From b66393e5879d5ae9fbdd726d30c741c9054b10df Mon Sep 17 00:00:00 2001
From: Matej Poklemba
Date: Tue, 17 Sep 2024 14:03:37 +0200
Subject: [PATCH 1/5] Add UI into the repo
---
.gitignore | 1 -
api3-aave-ui/.eslintrc.json | 3 +
api3-aave-ui/.gitignore | 40 +
api3-aave-ui/.npmrc | 1 +
api3-aave-ui/README.md | 33 +
api3-aave-ui/components/ConnectWallet.tsx | 89 +
api3-aave-ui/components/CurvesDecoration.tsx | 1354 ++++
api3-aave-ui/components/ExternalLinkIcon.tsx | 16 +
api3-aave-ui/components/Footer.tsx | 19 +
api3-aave-ui/components/Header.tsx | 43 +
api3-aave-ui/components/Layout.tsx | 14 +
api3-aave-ui/components/StakeCard.jsx | 86 +
api3-aave-ui/components/nav_mobile.tsx | 98 +
api3-aave-ui/components/pane.tsx | 24 +
api3-aave-ui/components/row.tsx | 32 +
api3-aave-ui/components/stake/StakeCard.tsx | 198 +
api3-aave-ui/components/stake/StakeHeader.tsx | 51 +
api3-aave-ui/configuration.ts | 152 +
api3-aave-ui/deployment-configs.json | 50 +
api3-aave-ui/favicon.ico | Bin 0 -> 270398 bytes
api3-aave-ui/marketConfig.json | 168 +
api3-aave-ui/next-env.d.ts | 5 +
api3-aave-ui/next.config.js | 13 +
api3-aave-ui/package.json | 54 +
api3-aave-ui/pages/_app.tsx | 87 +
api3-aave-ui/pages/asset-detail/index.tsx | 501 ++
api3-aave-ui/pages/dashboard/index.tsx | 212 +
api3-aave-ui/pages/index.tsx | 22 +
.../pages/markets/CompoundDashboard.tsx | 173 +
.../markets/MarketAssetListContainer.tsx | 52 +
.../pages/markets/MarketAssetsList.tsx | 139 +
.../compound/MarketAssetListContainerComp.tsx | 16 +
.../markets/compound/MarketAssetsListComp.tsx | 195 +
api3-aave-ui/pages/markets/index.tsx | 97 +
api3-aave-ui/pages/stake/index.tsx | 77 +
api3-aave-ui/postcss.config.js | 6 +
api3-aave-ui/prettier.config.js | 3 +
api3-aave-ui/public/images/favicon.png | Bin 0 -> 92196 bytes
.../public/images/footer-pattern-mobile.svg | 14 +
api3-aave-ui/public/images/footer-pattern.svg | 264 +
api3-aave-ui/public/images/logo-icon.svg | 118 +
api3-aave-ui/public/logos/DOV.png | Bin 0 -> 129538 bytes
api3-aave-ui/public/logos/ETH.png | Bin 0 -> 24070 bytes
api3-aave-ui/public/logos/OEVT.png | Bin 0 -> 2708 bytes
api3-aave-ui/public/logos/POL.png | Bin 0 -> 12427 bytes
api3-aave-ui/public/logos/PZM.png | Bin 0 -> 7405 bytes
api3-aave-ui/public/logos/PZM.svg | 22 +
api3-aave-ui/public/logos/USDC.png | Bin 0 -> 892 bytes
api3-aave-ui/public/logos/WBTC.png | Bin 0 -> 3768 bytes
api3-aave-ui/public/logos/WETH10.png | Bin 0 -> 3886 bytes
api3-aave-ui/src/abis/comet.json | 528 ++
.../src/components/ContentContainer.tsx | 21 +
.../src/components/ContentWithTooltip.tsx | 134 +
.../src/components/GasStation/GasButton.tsx | 26 +
.../src/components/GasStation/GasStation.tsx | 113 +
.../GasStation/GasStationProvider.tsx | 51 +
.../src/components/GhoBorrowApyRange.tsx | 100 +
.../src/components/HealthFactorNumber.tsx | 76 +
.../src/components/StyledToggleButton.tsx | 55 +
.../components/StyledToggleButtonGroup.tsx | 27 +
api3-aave-ui/src/components/SymbolIcon.tsx | 39 +
.../src/components/TextWithTooltip.tsx | 85 +
.../components/caps/CapsCircularStatus.tsx | 95 +
api3-aave-ui/src/components/caps/CapsHint.tsx | 65 +
.../src/components/caps/CapsTooltip.tsx | 57 +
.../src/components/caps/DebtCeilingStatus.tsx | 105 +
api3-aave-ui/src/components/caps/helper.ts | 4 +
.../BorrowAssetsList/BorrowAssetsList.tsx | 130 +
.../BorrowAssetsList/BorrowAssetsListItem.tsx | 101 +
.../dashboard/BorrowAssetsList/types.ts | 36 +
.../BorrowedPositionsList.tsx | 185 +
.../BorrowedPositionsListItem.tsx | 126 +
.../BorrowedPositionsListMobileItem.tsx | 155 +
.../GhoBorrowedPositionsListItem.tsx | 283 +
.../dashboard/BorrowedPositionsList/types.ts | 18 +
.../SuppliedPositionsList.tsx | 133 +
.../SuppliedPositionsListItem.tsx | 130 +
.../SuppliedPositionsListMobileItem.tsx | 134 +
.../SupplyAssetsList/SupplyAssetsList.tsx | 235 +
.../SupplyAssetsList/SupplyAssetsListItem.tsx | 117 +
.../SupplyAssetsListMobileItem.tsx | 52 +
.../dashboard/SupplyAssetsList/types.ts | 21 +
.../src/components/dashboard/emptyfile | 1 +
.../src/components/icons/LensIcon.tsx | 26 +
.../src/components/icons/LensterIcon.tsx | 27 +
.../src/components/icons/WalletIcon.tsx | 33 +
.../incentives/GhoIncentivesCard.tsx | 139 +
.../incentives/IncentivesButton.tsx | 183 +
.../components/incentives/IncentivesCard.tsx | 60 +
.../incentives/IncentivesTooltipContent.tsx | 111 +
.../infoTooltips/APYTypeTooltip.tsx | 16 +
.../infoTooltips/ApprovalTooltip.tsx | 20 +
.../infoTooltips/AvailableTooltip.tsx | 27 +
.../infoTooltips/BorrowCapMaxedTooltip.tsx | 43 +
.../infoTooltips/CollateralSwitchTooltip.tsx | 13 +
.../infoTooltips/DebtCeilingMaxedTooltip.tsx | 43 +
.../infoTooltips/FixedAPYTooltip.tsx | 35 +
.../components/infoTooltips/GasTooltip.tsx | 22 +
.../infoTooltips/PriceImpactTooltip.tsx | 73 +
.../infoTooltips/SlippageTooltip.tsx | 21 +
.../infoTooltips/SupplyCapMaxedTooltip.tsx | 43 +
.../isolationMode/IsolatedBadge.tsx | 126 +
.../src/components/primitives/BasicModal.tsx | 87 +
.../components/primitives/FormattedNumber.tsx | 186 +
.../src/components/primitives/Link.tsx | 128 +
.../src/components/primitives/NoData.tsx | 8 +
.../src/components/primitives/Row.tsx | 33 +
.../src/components/primitives/TokenIcon.tsx | 251 +
.../primitives/TypographyGradient.tsx | 17 +
.../src/components/primitives/Warning.tsx | 11 +
.../components/transactions/AssetInput.tsx | 344 +
.../transactions/Borrow/BorrowActions.tsx | 308 +
.../Borrow/BorrowAmountWarning.tsx | 46 +
.../transactions/Borrow/BorrowModal.tsx | 80 +
.../Borrow/BorrowModalContent.tsx | 419 ++
.../Borrow/GhoBorrowModalContent.tsx | 493 ++
.../Borrow/GhoBorrowSuccessView.tsx | 340 +
.../Borrow/ParameterChangewarning.tsx | 17 +
.../ClaimRewards/ClaimRewardsActions.tsx | 54 +
.../ClaimRewards/ClaimRewardsModal.tsx | 14 +
.../ClaimRewards/ClaimRewardsModalContent.tsx | 256 +
.../ClaimRewards/RewardsSelect.tsx | 112 +
.../CollateralChangeActions.tsx | 65 +
.../CollateralChangeModal.tsx | 32 +
.../CollateralChangeModalContent.tsx | 204 +
.../transactions/Emode/EmodeActions.tsx | 70 +
.../transactions/Emode/EmodeModal.tsx | 20 +
.../transactions/Emode/EmodeModalContent.tsx | 415 ++
.../transactions/Emode/EmodeNaming.ts | 6 +
.../transactions/Emode/EmodeSelect.tsx | 100 +
.../transactions/Emode/TxModalTitle.tsx | 15 +
.../ApprovalMethodToggleButton.tsx | 106 +
.../transactions/FlowCommons/Error.tsx | 77 +
.../FlowCommons/GasEstimationError.tsx | 44 +
.../transactions/FlowCommons/ModalWrapper.tsx | 277 +
.../FlowCommons/RightHelperText.tsx | 72 +
.../transactions/FlowCommons/SlippageList.tsx | 148 +
.../transactions/FlowCommons/Success.tsx | 224 +
.../FlowCommons/TxModalDetails.tsx | 454 ++
.../transactions/FlowCommons/TxModalTitle.tsx | 15 +
.../transactions/GasStation/GasButton.tsx | 40 +
.../transactions/GasStation/GasStation.tsx | 113 +
.../GasStation/GasStationProvider.tsx | 52 +
.../Repay/CollateralRepayActions.tsx | 153 +
.../Repay/CollateralRepayModalContent.tsx | 352 +
.../transactions/Repay/RepayActions.tsx | 102 +
.../transactions/Repay/RepayModal.tsx | 91 +
.../transactions/Repay/RepayModalContent.tsx | 309 +
.../transactions/Repay/RepayTypeSelector.tsx | 52 +
.../transactions/RightHelperText.tsx | 73 +
.../transactions/Stake/StakeActions.tsx | 90 +
.../transactions/Stake/StakeModal.tsx | 19 +
.../transactions/Stake/StakeModalContent.tsx | 165 +
.../StakeCooldown/StakeCooldownActions.tsx | 55 +
.../StakeCooldown/StakeCooldownModal.tsx | 14 +
.../StakeCooldownModalContent.tsx | 311 +
.../StakeRewardClaimActions.tsx | 54 +
.../StakeRewardClaimModal.tsx | 16 +
.../StakeRewardClaimModalContent.tsx | 148 +
.../StakeRewardClaimRestakeActions.tsx | 62 +
.../StakeRewardClaimRestakeModal.tsx | 19 +
.../StakeRewardClaimRestakeModalContent.tsx | 160 +
.../transactions/Supply/SupplyActions.tsx | 354 +
.../transactions/Supply/SupplyModal.tsx | 62 +
.../Supply/SupplyModalContent.tsx | 377 ++
.../transactions/TxActionsWrapper.tsx | 179 +
.../transactions/UnStake/UnStakeActions.tsx | 59 +
.../transactions/UnStake/UnStakeModal.tsx | 16 +
.../UnStake/UnStakeModalContent.tsx | 146 +
.../Warnings/BorrowCapWarning.tsx | 48 +
.../Warnings/ChangeNetworkWarning.tsx | 51 +
.../transactions/Warnings/CooldownWarning.tsx | 28 +
.../Warnings/DebtCeilingWarning.tsx | 48 +
.../Warnings/IsolationModeWarning.tsx | 31 +
.../Warnings/ParaswapErrorDisplay.tsx | 32 +
.../Warnings/SupplyCapWarning.tsx | 48 +
.../transactions/Withdraw/WithdrawActions.tsx | 73 +
.../transactions/Withdraw/WithdrawModal.tsx | 40 +
.../Withdraw/WithdrawModalContent.tsx | 330 +
.../src/components/transactions/utils.ts | 120 +
api3-aave-ui/src/helpers/compoundHelpers.ts | 385 ++
.../src/helpers/text-center-ellipsis.ts | 3 +
api3-aave-ui/src/helpers/timeHelper.tsx | 13 +
.../src/helpers/toggle-local-storage-click.ts | 13 +
api3-aave-ui/src/helpers/types.ts | 39 +
.../helpers/useParaSwapTransactionHandler.tsx | 378 ++
.../src/helpers/useTransactionHandler.tsx | 511 ++
.../BackgroundDataProvider.tsx | 50 +
.../app-data-provider/useAppDataProvider.tsx | 327 +
.../app-data-provider/useWalletBalances.tsx | 67 +
api3-aave-ui/src/hooks/lib/WagmiProvider.tsx | 80 +
api3-aave-ui/src/hooks/lib/WalletOptions.ts | 123 +
api3-aave-ui/src/hooks/lib/Web3Provider.tsx | 478 ++
api3-aave-ui/src/hooks/lib/chains.ts | 261 +
api3-aave-ui/src/hooks/lib/ethers.ts | 51 +
.../src/hooks/lib/hooks/use-get-ens.tsx | 63 +
.../src/hooks/lib/hooks/useWeb3Context.tsx | 23 +
api3-aave-ui/src/hooks/lib/useWeb3.ts | 70 +
api3-aave-ui/src/hooks/paraswap/common.ts | 444 ++
.../hooks/paraswap/useCollateralRepaySwap.tsx | 208 +
.../src/hooks/paraswap/useCollateralSwap.tsx | 165 +
.../src/hooks/paraswap/useDebtSwitch.tsx | 166 +
.../src/hooks/pool/usePoolTokensBalance.ts | 29 +
.../src/hooks/stake/useGeneralStakeUiData.ts | 12 +
.../src/hooks/stake/useUserStakeUiData.ts | 16 +
api3-aave-ui/src/hooks/useAssetCaps.tsx | 183 +
.../src/hooks/useCurrentTimestamp.tsx | 28 +
api3-aave-ui/src/hooks/useGasStation.tsx | 11 +
api3-aave-ui/src/hooks/useGetGasPrices.tsx | 85 +
api3-aave-ui/src/hooks/useIsWrongNetwork.tsx | 18 +
api3-aave-ui/src/hooks/useModal.tsx | 279 +
api3-aave-ui/src/hooks/usePolling.tsx | 46 +
.../src/hooks/useProtocolDataContext.tsx | 22 +
api3-aave-ui/src/layouts/AppGlobalStyles.tsx | 60 +
.../src/services/UiStakeDataService.ts | 36 +
.../src/services/WalletBalanceService.ts | 84 +
api3-aave-ui/src/store/compoundSlice.ts | 234 +
api3-aave-ui/src/store/ghoSlice.ts | 155 +
api3-aave-ui/src/store/governanceSlice.ts | 124 +
api3-aave-ui/src/store/incentiveSlice.ts | 65 +
api3-aave-ui/src/store/layoutSlice.ts | 22 +
api3-aave-ui/src/store/poolSelectors.ts | 248 +
api3-aave-ui/src/store/poolSlice.ts | 887 +++
api3-aave-ui/src/store/protocolDataSlice.ts | 81 +
api3-aave-ui/src/store/root.ts | 187 +
api3-aave-ui/src/store/stakeSlice.ts | 117 +
.../src/store/transactionsSelectors.ts | 24 +
api3-aave-ui/src/store/transactionsSlice.ts | 61 +
.../store/utils/createSingletonSubscriber.ts | 40 +
.../src/store/utils/domain-fetchers/ens.ts | 34 +
.../src/store/utils/domain-fetchers/index.ts | 3 +
api3-aave-ui/src/store/utils/queryParams.ts | 25 +
.../src/store/v3MigrationSelectors.ts | 1055 +++
api3-aave-ui/src/store/v3MigrationSlice.ts | 453 ++
api3-aave-ui/src/store/walletDomains.ts | 48 +
api3-aave-ui/src/store/walletSlice.ts | 95 +
.../ui-config/SharedDependenciesProvider.tsx | 92 +
api3-aave-ui/src/ui-config/errorMapping.tsx | 188 +
api3-aave-ui/src/ui-config/generatedConfig.ts | 3 +
.../src/ui-config/governanceConfig.ts | 51 +
.../src/ui-config/localMarketConfigs.ts | 53 +
api3-aave-ui/src/ui-config/marketsConfig.tsx | 159 +
api3-aave-ui/src/ui-config/networksConfig.ts | 405 ++
api3-aave-ui/src/ui-config/permitConfig.ts | 47 +
api3-aave-ui/src/ui-config/queries.ts | 12 +
api3-aave-ui/src/ui-config/queries.tsx | 12 +
api3-aave-ui/src/ui-config/reservePatches.ts | 162 +
api3-aave-ui/src/ui-config/stakeConfig.ts | 30 +
.../utils/__tests__/RotationProvider.test.ts | 145 +
.../src/utils/__tests__/ghoUtilities.spec.ts | 50 +
.../__tests__/marketsAndNetworkConfig.spec.ts | 9 +
api3-aave-ui/src/utils/dashboardSortUtils.ts | 151 +
api3-aave-ui/src/utils/eMode.ts | 5 +
.../utils/getMaxAmountAvailableToBorrow.ts | 168 +
.../utils/getMaxAmountAvailableToSupply.ts | 59 +
api3-aave-ui/src/utils/ghoUtilities.tsx | 95 +
api3-aave-ui/src/utils/hfUtils.ts | 163 +
.../src/utils/marketsAndNetworksConfig.ts | 321 +
api3-aave-ui/src/utils/mixPanelEvents.ts | 106 +
api3-aave-ui/src/utils/rotationProvider.ts | 144 +
api3-aave-ui/src/utils/tFetch.ts | 11 +
api3-aave-ui/src/utils/theme.tsx | 682 ++
api3-aave-ui/src/utils/types.ts | 3 +
api3-aave-ui/src/utils/utils.ts | 83 +
api3-aave-ui/styles/colors.css | 88 +
api3-aave-ui/styles/components.css | 211 +
api3-aave-ui/styles/developer-styles.css | 16 +
api3-aave-ui/styles/forms.css | 162 +
api3-aave-ui/styles/preset.css | 4 +
api3-aave-ui/styles/reset.css | 146 +
api3-aave-ui/styles/settings.css | 228 +
api3-aave-ui/styles/setup.css | 58 +
api3-aave-ui/styles/site.css | 106 +
api3-aave-ui/styles/structure.css | 40 +
api3-aave-ui/styles/typography.css | 155 +
api3-aave-ui/styles/utilities.css | 353 +
api3-aave-ui/tailwind.config.js | 866 +++
api3-aave-ui/tsconfig.json | 48 +
api3-aave-ui/yarn.lock | 5714 +++++++++++++++++
279 files changed, 39469 insertions(+), 1 deletion(-)
create mode 100644 api3-aave-ui/.eslintrc.json
create mode 100644 api3-aave-ui/.gitignore
create mode 100644 api3-aave-ui/.npmrc
create mode 100644 api3-aave-ui/README.md
create mode 100644 api3-aave-ui/components/ConnectWallet.tsx
create mode 100644 api3-aave-ui/components/CurvesDecoration.tsx
create mode 100644 api3-aave-ui/components/ExternalLinkIcon.tsx
create mode 100644 api3-aave-ui/components/Footer.tsx
create mode 100644 api3-aave-ui/components/Header.tsx
create mode 100644 api3-aave-ui/components/Layout.tsx
create mode 100644 api3-aave-ui/components/StakeCard.jsx
create mode 100644 api3-aave-ui/components/nav_mobile.tsx
create mode 100644 api3-aave-ui/components/pane.tsx
create mode 100644 api3-aave-ui/components/row.tsx
create mode 100644 api3-aave-ui/components/stake/StakeCard.tsx
create mode 100644 api3-aave-ui/components/stake/StakeHeader.tsx
create mode 100644 api3-aave-ui/configuration.ts
create mode 100644 api3-aave-ui/deployment-configs.json
create mode 100644 api3-aave-ui/favicon.ico
create mode 100644 api3-aave-ui/marketConfig.json
create mode 100644 api3-aave-ui/next-env.d.ts
create mode 100644 api3-aave-ui/next.config.js
create mode 100644 api3-aave-ui/package.json
create mode 100644 api3-aave-ui/pages/_app.tsx
create mode 100644 api3-aave-ui/pages/asset-detail/index.tsx
create mode 100644 api3-aave-ui/pages/dashboard/index.tsx
create mode 100644 api3-aave-ui/pages/index.tsx
create mode 100644 api3-aave-ui/pages/markets/CompoundDashboard.tsx
create mode 100644 api3-aave-ui/pages/markets/MarketAssetListContainer.tsx
create mode 100644 api3-aave-ui/pages/markets/MarketAssetsList.tsx
create mode 100644 api3-aave-ui/pages/markets/compound/MarketAssetListContainerComp.tsx
create mode 100644 api3-aave-ui/pages/markets/compound/MarketAssetsListComp.tsx
create mode 100644 api3-aave-ui/pages/markets/index.tsx
create mode 100644 api3-aave-ui/pages/stake/index.tsx
create mode 100644 api3-aave-ui/postcss.config.js
create mode 100644 api3-aave-ui/prettier.config.js
create mode 100644 api3-aave-ui/public/images/favicon.png
create mode 100644 api3-aave-ui/public/images/footer-pattern-mobile.svg
create mode 100644 api3-aave-ui/public/images/footer-pattern.svg
create mode 100644 api3-aave-ui/public/images/logo-icon.svg
create mode 100644 api3-aave-ui/public/logos/DOV.png
create mode 100644 api3-aave-ui/public/logos/ETH.png
create mode 100644 api3-aave-ui/public/logos/OEVT.png
create mode 100644 api3-aave-ui/public/logos/POL.png
create mode 100644 api3-aave-ui/public/logos/PZM.png
create mode 100644 api3-aave-ui/public/logos/PZM.svg
create mode 100644 api3-aave-ui/public/logos/USDC.png
create mode 100644 api3-aave-ui/public/logos/WBTC.png
create mode 100644 api3-aave-ui/public/logos/WETH10.png
create mode 100644 api3-aave-ui/src/abis/comet.json
create mode 100644 api3-aave-ui/src/components/ContentContainer.tsx
create mode 100644 api3-aave-ui/src/components/ContentWithTooltip.tsx
create mode 100644 api3-aave-ui/src/components/GasStation/GasButton.tsx
create mode 100644 api3-aave-ui/src/components/GasStation/GasStation.tsx
create mode 100644 api3-aave-ui/src/components/GasStation/GasStationProvider.tsx
create mode 100644 api3-aave-ui/src/components/GhoBorrowApyRange.tsx
create mode 100644 api3-aave-ui/src/components/HealthFactorNumber.tsx
create mode 100644 api3-aave-ui/src/components/StyledToggleButton.tsx
create mode 100644 api3-aave-ui/src/components/StyledToggleButtonGroup.tsx
create mode 100644 api3-aave-ui/src/components/SymbolIcon.tsx
create mode 100644 api3-aave-ui/src/components/TextWithTooltip.tsx
create mode 100644 api3-aave-ui/src/components/caps/CapsCircularStatus.tsx
create mode 100644 api3-aave-ui/src/components/caps/CapsHint.tsx
create mode 100644 api3-aave-ui/src/components/caps/CapsTooltip.tsx
create mode 100644 api3-aave-ui/src/components/caps/DebtCeilingStatus.tsx
create mode 100644 api3-aave-ui/src/components/caps/helper.ts
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowAssetsList/BorrowAssetsList.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowAssetsList/BorrowAssetsListItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowAssetsList/types.ts
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowedPositionsList/BorrowedPositionsList.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowedPositionsList/BorrowedPositionsListItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowedPositionsList/BorrowedPositionsListMobileItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowedPositionsList/GhoBorrowedPositionsListItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/BorrowedPositionsList/types.ts
create mode 100644 api3-aave-ui/src/components/dashboard/SuppliedPositionsList /SuppliedPositionsList.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/SuppliedPositionsList /SuppliedPositionsListItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/SuppliedPositionsList /SuppliedPositionsListMobileItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/SupplyAssetsList/SupplyAssetsList.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/SupplyAssetsList/SupplyAssetsListItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/SupplyAssetsList/SupplyAssetsListMobileItem.tsx
create mode 100644 api3-aave-ui/src/components/dashboard/SupplyAssetsList/types.ts
create mode 100644 api3-aave-ui/src/components/dashboard/emptyfile
create mode 100644 api3-aave-ui/src/components/icons/LensIcon.tsx
create mode 100644 api3-aave-ui/src/components/icons/LensterIcon.tsx
create mode 100644 api3-aave-ui/src/components/icons/WalletIcon.tsx
create mode 100644 api3-aave-ui/src/components/incentives/GhoIncentivesCard.tsx
create mode 100644 api3-aave-ui/src/components/incentives/IncentivesButton.tsx
create mode 100644 api3-aave-ui/src/components/incentives/IncentivesCard.tsx
create mode 100644 api3-aave-ui/src/components/incentives/IncentivesTooltipContent.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/APYTypeTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/ApprovalTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/AvailableTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/BorrowCapMaxedTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/CollateralSwitchTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/DebtCeilingMaxedTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/FixedAPYTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/GasTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/PriceImpactTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/SlippageTooltip.tsx
create mode 100644 api3-aave-ui/src/components/infoTooltips/SupplyCapMaxedTooltip.tsx
create mode 100644 api3-aave-ui/src/components/isolationMode/IsolatedBadge.tsx
create mode 100644 api3-aave-ui/src/components/primitives/BasicModal.tsx
create mode 100644 api3-aave-ui/src/components/primitives/FormattedNumber.tsx
create mode 100644 api3-aave-ui/src/components/primitives/Link.tsx
create mode 100644 api3-aave-ui/src/components/primitives/NoData.tsx
create mode 100644 api3-aave-ui/src/components/primitives/Row.tsx
create mode 100644 api3-aave-ui/src/components/primitives/TokenIcon.tsx
create mode 100644 api3-aave-ui/src/components/primitives/TypographyGradient.tsx
create mode 100644 api3-aave-ui/src/components/primitives/Warning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/AssetInput.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Borrow/BorrowActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Borrow/BorrowAmountWarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Borrow/BorrowModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Borrow/BorrowModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Borrow/GhoBorrowModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Borrow/GhoBorrowSuccessView.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Borrow/ParameterChangewarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/ClaimRewards/ClaimRewardsActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/ClaimRewards/ClaimRewardsModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/ClaimRewards/ClaimRewardsModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/ClaimRewards/RewardsSelect.tsx
create mode 100644 api3-aave-ui/src/components/transactions/CollateralChange/CollateralChangeActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/CollateralChange/CollateralChangeModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/CollateralChange/CollateralChangeModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Emode/EmodeActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Emode/EmodeModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Emode/EmodeModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Emode/EmodeNaming.ts
create mode 100644 api3-aave-ui/src/components/transactions/Emode/EmodeSelect.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Emode/TxModalTitle.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/ApprovalMethodToggleButton.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/Error.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/GasEstimationError.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/ModalWrapper.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/RightHelperText.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/SlippageList.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/Success.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/TxModalDetails.tsx
create mode 100644 api3-aave-ui/src/components/transactions/FlowCommons/TxModalTitle.tsx
create mode 100644 api3-aave-ui/src/components/transactions/GasStation/GasButton.tsx
create mode 100644 api3-aave-ui/src/components/transactions/GasStation/GasStation.tsx
create mode 100644 api3-aave-ui/src/components/transactions/GasStation/GasStationProvider.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Repay/CollateralRepayActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Repay/CollateralRepayModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Repay/RepayActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Repay/RepayModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Repay/RepayModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Repay/RepayTypeSelector.tsx
create mode 100644 api3-aave-ui/src/components/transactions/RightHelperText.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Stake/StakeActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Stake/StakeModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Stake/StakeModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeCooldown/StakeCooldownActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeCooldown/StakeCooldownModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeCooldown/StakeCooldownModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeRewardClaim/StakeRewardClaimActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeRewardClaim/StakeRewardClaimModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeRewardClaim/StakeRewardClaimModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeRewardClaimRestake/StakeRewardClaimRestakeActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeRewardClaimRestake/StakeRewardClaimRestakeModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/StakeRewardClaimRestake/StakeRewardClaimRestakeModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Supply/SupplyActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Supply/SupplyModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Supply/SupplyModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/TxActionsWrapper.tsx
create mode 100644 api3-aave-ui/src/components/transactions/UnStake/UnStakeActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/UnStake/UnStakeModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/UnStake/UnStakeModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Warnings/BorrowCapWarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Warnings/ChangeNetworkWarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Warnings/CooldownWarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Warnings/DebtCeilingWarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Warnings/IsolationModeWarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Warnings/ParaswapErrorDisplay.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Warnings/SupplyCapWarning.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Withdraw/WithdrawActions.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Withdraw/WithdrawModal.tsx
create mode 100644 api3-aave-ui/src/components/transactions/Withdraw/WithdrawModalContent.tsx
create mode 100644 api3-aave-ui/src/components/transactions/utils.ts
create mode 100644 api3-aave-ui/src/helpers/compoundHelpers.ts
create mode 100644 api3-aave-ui/src/helpers/text-center-ellipsis.ts
create mode 100644 api3-aave-ui/src/helpers/timeHelper.tsx
create mode 100644 api3-aave-ui/src/helpers/toggle-local-storage-click.ts
create mode 100644 api3-aave-ui/src/helpers/types.ts
create mode 100644 api3-aave-ui/src/helpers/useParaSwapTransactionHandler.tsx
create mode 100644 api3-aave-ui/src/helpers/useTransactionHandler.tsx
create mode 100644 api3-aave-ui/src/hooks/app-data-provider/BackgroundDataProvider.tsx
create mode 100644 api3-aave-ui/src/hooks/app-data-provider/useAppDataProvider.tsx
create mode 100644 api3-aave-ui/src/hooks/app-data-provider/useWalletBalances.tsx
create mode 100644 api3-aave-ui/src/hooks/lib/WagmiProvider.tsx
create mode 100644 api3-aave-ui/src/hooks/lib/WalletOptions.ts
create mode 100644 api3-aave-ui/src/hooks/lib/Web3Provider.tsx
create mode 100644 api3-aave-ui/src/hooks/lib/chains.ts
create mode 100644 api3-aave-ui/src/hooks/lib/ethers.ts
create mode 100644 api3-aave-ui/src/hooks/lib/hooks/use-get-ens.tsx
create mode 100644 api3-aave-ui/src/hooks/lib/hooks/useWeb3Context.tsx
create mode 100644 api3-aave-ui/src/hooks/lib/useWeb3.ts
create mode 100644 api3-aave-ui/src/hooks/paraswap/common.ts
create mode 100644 api3-aave-ui/src/hooks/paraswap/useCollateralRepaySwap.tsx
create mode 100644 api3-aave-ui/src/hooks/paraswap/useCollateralSwap.tsx
create mode 100644 api3-aave-ui/src/hooks/paraswap/useDebtSwitch.tsx
create mode 100644 api3-aave-ui/src/hooks/pool/usePoolTokensBalance.ts
create mode 100644 api3-aave-ui/src/hooks/stake/useGeneralStakeUiData.ts
create mode 100644 api3-aave-ui/src/hooks/stake/useUserStakeUiData.ts
create mode 100644 api3-aave-ui/src/hooks/useAssetCaps.tsx
create mode 100644 api3-aave-ui/src/hooks/useCurrentTimestamp.tsx
create mode 100644 api3-aave-ui/src/hooks/useGasStation.tsx
create mode 100644 api3-aave-ui/src/hooks/useGetGasPrices.tsx
create mode 100644 api3-aave-ui/src/hooks/useIsWrongNetwork.tsx
create mode 100644 api3-aave-ui/src/hooks/useModal.tsx
create mode 100644 api3-aave-ui/src/hooks/usePolling.tsx
create mode 100644 api3-aave-ui/src/hooks/useProtocolDataContext.tsx
create mode 100644 api3-aave-ui/src/layouts/AppGlobalStyles.tsx
create mode 100644 api3-aave-ui/src/services/UiStakeDataService.ts
create mode 100644 api3-aave-ui/src/services/WalletBalanceService.ts
create mode 100644 api3-aave-ui/src/store/compoundSlice.ts
create mode 100644 api3-aave-ui/src/store/ghoSlice.ts
create mode 100644 api3-aave-ui/src/store/governanceSlice.ts
create mode 100644 api3-aave-ui/src/store/incentiveSlice.ts
create mode 100644 api3-aave-ui/src/store/layoutSlice.ts
create mode 100644 api3-aave-ui/src/store/poolSelectors.ts
create mode 100644 api3-aave-ui/src/store/poolSlice.ts
create mode 100644 api3-aave-ui/src/store/protocolDataSlice.ts
create mode 100644 api3-aave-ui/src/store/root.ts
create mode 100644 api3-aave-ui/src/store/stakeSlice.ts
create mode 100644 api3-aave-ui/src/store/transactionsSelectors.ts
create mode 100644 api3-aave-ui/src/store/transactionsSlice.ts
create mode 100644 api3-aave-ui/src/store/utils/createSingletonSubscriber.ts
create mode 100644 api3-aave-ui/src/store/utils/domain-fetchers/ens.ts
create mode 100644 api3-aave-ui/src/store/utils/domain-fetchers/index.ts
create mode 100644 api3-aave-ui/src/store/utils/queryParams.ts
create mode 100644 api3-aave-ui/src/store/v3MigrationSelectors.ts
create mode 100644 api3-aave-ui/src/store/v3MigrationSlice.ts
create mode 100644 api3-aave-ui/src/store/walletDomains.ts
create mode 100644 api3-aave-ui/src/store/walletSlice.ts
create mode 100644 api3-aave-ui/src/ui-config/SharedDependenciesProvider.tsx
create mode 100644 api3-aave-ui/src/ui-config/errorMapping.tsx
create mode 100644 api3-aave-ui/src/ui-config/generatedConfig.ts
create mode 100644 api3-aave-ui/src/ui-config/governanceConfig.ts
create mode 100644 api3-aave-ui/src/ui-config/localMarketConfigs.ts
create mode 100644 api3-aave-ui/src/ui-config/marketsConfig.tsx
create mode 100644 api3-aave-ui/src/ui-config/networksConfig.ts
create mode 100644 api3-aave-ui/src/ui-config/permitConfig.ts
create mode 100644 api3-aave-ui/src/ui-config/queries.ts
create mode 100644 api3-aave-ui/src/ui-config/queries.tsx
create mode 100644 api3-aave-ui/src/ui-config/reservePatches.ts
create mode 100644 api3-aave-ui/src/ui-config/stakeConfig.ts
create mode 100644 api3-aave-ui/src/utils/__tests__/RotationProvider.test.ts
create mode 100644 api3-aave-ui/src/utils/__tests__/ghoUtilities.spec.ts
create mode 100644 api3-aave-ui/src/utils/__tests__/marketsAndNetworkConfig.spec.ts
create mode 100644 api3-aave-ui/src/utils/dashboardSortUtils.ts
create mode 100644 api3-aave-ui/src/utils/eMode.ts
create mode 100644 api3-aave-ui/src/utils/getMaxAmountAvailableToBorrow.ts
create mode 100644 api3-aave-ui/src/utils/getMaxAmountAvailableToSupply.ts
create mode 100644 api3-aave-ui/src/utils/ghoUtilities.tsx
create mode 100644 api3-aave-ui/src/utils/hfUtils.ts
create mode 100644 api3-aave-ui/src/utils/marketsAndNetworksConfig.ts
create mode 100644 api3-aave-ui/src/utils/mixPanelEvents.ts
create mode 100644 api3-aave-ui/src/utils/rotationProvider.ts
create mode 100644 api3-aave-ui/src/utils/tFetch.ts
create mode 100644 api3-aave-ui/src/utils/theme.tsx
create mode 100644 api3-aave-ui/src/utils/types.ts
create mode 100644 api3-aave-ui/src/utils/utils.ts
create mode 100644 api3-aave-ui/styles/colors.css
create mode 100644 api3-aave-ui/styles/components.css
create mode 100644 api3-aave-ui/styles/developer-styles.css
create mode 100644 api3-aave-ui/styles/forms.css
create mode 100644 api3-aave-ui/styles/preset.css
create mode 100644 api3-aave-ui/styles/reset.css
create mode 100644 api3-aave-ui/styles/settings.css
create mode 100644 api3-aave-ui/styles/setup.css
create mode 100644 api3-aave-ui/styles/site.css
create mode 100644 api3-aave-ui/styles/structure.css
create mode 100644 api3-aave-ui/styles/typography.css
create mode 100644 api3-aave-ui/styles/utilities.css
create mode 100644 api3-aave-ui/tailwind.config.js
create mode 100644 api3-aave-ui/tsconfig.json
create mode 100644 api3-aave-ui/yarn.lock
diff --git a/.gitignore b/.gitignore
index aff2fd7f4..2c551ddec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,5 @@ typechain/
test-results.json
scenario-results.json
-api3-aave-ui/
api3-adaptors/deployments/
\ No newline at end of file
diff --git a/api3-aave-ui/.eslintrc.json b/api3-aave-ui/.eslintrc.json
new file mode 100644
index 000000000..bffb357a7
--- /dev/null
+++ b/api3-aave-ui/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/api3-aave-ui/.gitignore b/api3-aave-ui/.gitignore
new file mode 100644
index 000000000..f2bac5699
--- /dev/null
+++ b/api3-aave-ui/.gitignore
@@ -0,0 +1,40 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# local env files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+
+/generated-configs
diff --git a/api3-aave-ui/.npmrc b/api3-aave-ui/.npmrc
new file mode 100644
index 000000000..aff8a3283
--- /dev/null
+++ b/api3-aave-ui/.npmrc
@@ -0,0 +1 @@
+strict-peer-dependencies = false
diff --git a/api3-aave-ui/README.md b/api3-aave-ui/README.md
new file mode 100644
index 000000000..31bea9e6a
--- /dev/null
+++ b/api3-aave-ui/README.md
@@ -0,0 +1,33 @@
+[](https://www.gnu.org/licenses/agpl-3.0)
+
+# API3 Aave UI
+
+This repository is being used in [Aave Protocol V2 Fork](https://github.com/api3-ecosystem/aave-protocol-v2-fork) to spin up market frontend. follow the docs the in [Aave Protocol V2 Fork](https://github.com/api3-ecosystem/aave-protocol-v2-fork) to run frontend on custom networks
+
+## What is Aave?
+
+Aave is a decentralized non-custodial liquidity markets protocol where users can participate as depositors or borrowers. Depositors provide liquidity to the market to earn a passive income, while borrowers are able to borrow in an overcollateralized (perpetually) or undercollateralized (one-block liquidity) fashion.
+
+## What is API3
+
+API3 is a collaborative project to deliver traditional API services to smart contract platforms in a decentralized and trust-minimized way.
+
+API3 is building secure first-party oracles and OEV-enabled data feeds for DeFi protocols and users. The data feeds are continuously updated by first-party oracles using signed data.
+
+## Setup
+
+The repository uses `deployment-configs.json` to load market configs. By default it uses default configs, and it uses defined configs if started from [Aave Protocol V2 Fork](https://github.com/api3-ecosystem/aave-protocol-v2-fork).
+
+### Spinning up the frontend locally with defaults
+
+- Install dependencies`
+
+ ```bash
+ yarn
+ ```
+
+- Start next client
+
+ ```bash
+ yarn dev
+ ```
diff --git a/api3-aave-ui/components/ConnectWallet.tsx b/api3-aave-ui/components/ConnectWallet.tsx
new file mode 100644
index 000000000..8b42dec6a
--- /dev/null
+++ b/api3-aave-ui/components/ConnectWallet.tsx
@@ -0,0 +1,89 @@
+import { Wallet } from "@mui/icons-material";
+import { ConnectButton } from "@rainbow-me/rainbowkit";
+
+export default function ConnectWallet() {
+ return (
+
+ {({
+ account,
+ chain,
+ openAccountModal,
+ openChainModal,
+ openConnectModal,
+ authenticationStatus,
+ mounted,
+ }) => {
+ // Note: If your app doesn't use authentication, you
+ // can remove all 'authenticationStatus' checks
+ const ready = mounted && authenticationStatus !== "loading";
+ const connected =
+ ready &&
+ account &&
+ chain &&
+ (!authenticationStatus || authenticationStatus === "authenticated");
+
+ console.log("chain", chain);
+ return (
+
+ {(() => {
+ if (!connected) {
+ return (
+
+ );
+ }
+ if (chain.unsupported) {
+ return (
+
+ );
+ }
+ return (
+
+ );
+ })()}
+
+ );
+ }}
+
+ );
+}
diff --git a/api3-aave-ui/components/CurvesDecoration.tsx b/api3-aave-ui/components/CurvesDecoration.tsx
new file mode 100644
index 000000000..a7b668ae5
--- /dev/null
+++ b/api3-aave-ui/components/CurvesDecoration.tsx
@@ -0,0 +1,1354 @@
+export default function CurvesDecoration() {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/api3-aave-ui/components/ExternalLinkIcon.tsx b/api3-aave-ui/components/ExternalLinkIcon.tsx
new file mode 100644
index 000000000..5c5d90e4f
--- /dev/null
+++ b/api3-aave-ui/components/ExternalLinkIcon.tsx
@@ -0,0 +1,16 @@
+export default function ExternalLinkIcon() {
+ return (
+
+ );
+}
diff --git a/api3-aave-ui/components/Footer.tsx b/api3-aave-ui/components/Footer.tsx
new file mode 100644
index 000000000..39fee6104
--- /dev/null
+++ b/api3-aave-ui/components/Footer.tsx
@@ -0,0 +1,19 @@
+export default function Footer() {
+ return (
+
+ );
+}
diff --git a/api3-aave-ui/components/Header.tsx b/api3-aave-ui/components/Header.tsx
new file mode 100644
index 000000000..a58b59b7b
--- /dev/null
+++ b/api3-aave-ui/components/Header.tsx
@@ -0,0 +1,43 @@
+import React from "react";
+import Link from "next/link";
+import ConnectWallet from "./ConnectWallet";
+import { populateChainConfigs } from "configuration";
+
+export default function Header() {
+ const currenChainConfig = populateChainConfigs();
+ return (
+
+
+
+
+
+
+
+
+ {currenChainConfig.currentMarket !== "compound" && (
+ -
+
+ Dashboard
+
+
+ )}
+
+ -
+
+ Markets
+
+
+ {/* -
+
+ Stake
+
+
*/}
+ -
+
+
+
+
+
+
+ );
+}
diff --git a/api3-aave-ui/components/Layout.tsx b/api3-aave-ui/components/Layout.tsx
new file mode 100644
index 000000000..d490732ad
--- /dev/null
+++ b/api3-aave-ui/components/Layout.tsx
@@ -0,0 +1,14 @@
+import Header from "./Header";
+import Footer from "./Footer";
+import CurvesDecoration from "./CurvesDecoration";
+
+export default function Layout({ children }: any) {
+ return (
+ <>
+
+
+ {children}
+
+ >
+ );
+}
diff --git a/api3-aave-ui/components/StakeCard.jsx b/api3-aave-ui/components/StakeCard.jsx
new file mode 100644
index 000000000..cf3e45fbf
--- /dev/null
+++ b/api3-aave-ui/components/StakeCard.jsx
@@ -0,0 +1,86 @@
+import Image from "next/image";
+import Link from "next/link";
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+
+export default function StakeCard(props) {
+ return (
+
+
+
+
+
+
Stake {props.chain}
+
+
+
+
+
+
+
+
Staked {props.chain}
+
+
+
+
+
+
+
+
+
+
+
Cooldown period
+
+ 20d
+
+
+
+
+
Claimable {props.chain}
+
+
+
+
+
+
+
+
+
+
+
+
{props.chain} per month
+
+ 0
+
+
+
+
+
+ );
+}
diff --git a/api3-aave-ui/components/nav_mobile.tsx b/api3-aave-ui/components/nav_mobile.tsx
new file mode 100644
index 000000000..c597052cf
--- /dev/null
+++ b/api3-aave-ui/components/nav_mobile.tsx
@@ -0,0 +1,98 @@
+import React from "react";
+import Link from "next/link";
+import { useRouter } from "next/router";
+
+interface MobileNavProps {
+ open: boolean;
+ onClose: () => void;
+}
+
+const MobileNav: React.FC = ({ open, onClose }) => {
+ const router = useRouter();
+
+ if (!open) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+
Phantazm
+
+
+
+
Dashboard
+
+
+
+
Markets
+
+
+
+
Docs
+
+
+
+
+
+
+
+ {/* Add more socials as needed */}
+
+
+
+
+ );
+};
+
+export default MobileNav;
diff --git a/api3-aave-ui/components/pane.tsx b/api3-aave-ui/components/pane.tsx
new file mode 100644
index 000000000..ab8765fce
--- /dev/null
+++ b/api3-aave-ui/components/pane.tsx
@@ -0,0 +1,24 @@
+import React from "react";
+
+interface PaneProps {
+ fullWidth: boolean;
+ title?: string;
+ children: React.ReactNode;
+}
+
+const Pane: React.FC = ({ fullWidth, title, children }) => {
+ return (
+
+ {title !== "" &&
{title}
}
+
{children}
+
+ );
+};
+
+export default Pane;
diff --git a/api3-aave-ui/components/row.tsx b/api3-aave-ui/components/row.tsx
new file mode 100644
index 000000000..016151c98
--- /dev/null
+++ b/api3-aave-ui/components/row.tsx
@@ -0,0 +1,32 @@
+import React from "react";
+import Image from "next/image";
+
+interface RowProps {
+ ticker: string;
+ name: string;
+ children: React.ReactNode;
+ subtitle: React.ReactNode;
+}
+
+const Row: React.FC = ({ ticker, name, subtitle, children }) => {
+ return (
+
+
+
+
+
{name}
+ {/* Well the balances will show even if wallet is not connected because it's not functional */}
+
{subtitle}
+
+
+ {children}
+
+ );
+};
+
+export default Row;
diff --git a/api3-aave-ui/components/stake/StakeCard.tsx b/api3-aave-ui/components/stake/StakeCard.tsx
new file mode 100644
index 000000000..ec64e0beb
--- /dev/null
+++ b/api3-aave-ui/components/stake/StakeCard.tsx
@@ -0,0 +1,198 @@
+import { valueToBigNumber } from "@aave/math-utils";
+import {
+ GeneralStakeUIDataHumanized,
+ GetUserStakeUIDataHumanized,
+} from "contract-helpers/dist/esm/uiStakeDataProvider-contract/types";
+import { BigNumber } from "ethers";
+import { formatEther, formatUnits } from "ethers/lib/utils";
+import Image from "next/image";
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+import { useCurrentTimestamp } from "src/hooks/useCurrentTimestamp";
+
+export interface StakingPanelProps {
+ onStakeAction?: () => void;
+ onStakeRewardClaimAction?: () => void;
+ onStakeRewardClaimRestakeAction?: () => void;
+ onCooldownAction?: () => void;
+ onUnstakeAction?: () => void;
+ stakeData?: GeneralStakeUIDataHumanized["aave"];
+ stakeUserData?: GetUserStakeUIDataHumanized["aave"];
+ description?: React.ReactNode;
+ headerAction?: React.ReactNode;
+ ethPriceUsd?: string;
+ stakeTitle: string;
+ stakedToken: string;
+ maxSlash: string;
+ icon: string;
+ hasDiscountProgram?: boolean;
+}
+
+export default function StakeCard({
+ onStakeAction,
+ onStakeRewardClaimAction,
+ onStakeRewardClaimRestakeAction,
+ onCooldownAction,
+ onUnstakeAction,
+ stakeTitle,
+ stakedToken,
+ description,
+ headerAction,
+ icon,
+ stakeData,
+ stakeUserData,
+ ethPriceUsd,
+ maxSlash,
+ hasDiscountProgram,
+}: StakingPanelProps) {
+ const now = useCurrentTimestamp(1);
+
+ // Cooldown logic
+ const stakeCooldownSeconds = stakeData?.stakeCooldownSeconds || 0;
+ const userCooldown = stakeUserData?.userCooldownTimestamp || 0;
+ const stakeUnstakeWindow = stakeData?.stakeUnstakeWindow || 0;
+
+ const userCooldownDelta = now - userCooldown;
+ const isCooldownActive =
+ userCooldownDelta < stakeCooldownSeconds + stakeUnstakeWindow;
+ const isUnstakeWindowActive =
+ isCooldownActive &&
+ userCooldownDelta > stakeCooldownSeconds &&
+ userCooldownDelta < stakeUnstakeWindow + stakeCooldownSeconds;
+
+ // Others
+ const availableToStake = formatEther(
+ BigNumber.from(stakeUserData?.underlyingTokenUserBalance || "0"),
+ );
+
+ const availableToReactivateCooldown =
+ isCooldownActive &&
+ BigNumber.from(stakeUserData?.stakeTokenRedeemableAmount || 0).gt(
+ stakeUserData?.userCooldownAmount || 0,
+ );
+
+ const stakedUSD = formatUnits(
+ BigNumber.from(stakeUserData?.stakeTokenRedeemableAmount || "0")
+ .mul(stakeData?.stakeTokenPriceEth || "0")
+ .mul(ethPriceUsd || "1"),
+ 18 + 18 + 8, // userBalance (18), stakedTokenPriceEth (18), ethPriceUsd (8)
+ );
+
+ const claimableUSD = formatUnits(
+ BigNumber.from(stakeUserData?.userIncentivesToClaim || "0")
+ .mul(stakeData?.rewardTokenPriceEth || "0")
+ .mul(ethPriceUsd || "1"),
+ 18 + 18 + 8, // incentivesBalance (18), rewardTokenPriceEth (18), ethPriceUsd (8)
+ );
+
+ const aavePerMonth = formatEther(
+ valueToBigNumber(stakeUserData?.stakeTokenRedeemableAmount || "0")
+ .dividedBy(stakeData?.stakeTokenTotalSupply || "1")
+ .multipliedBy(stakeData?.distributionPerSecond || "0")
+ .multipliedBy("2592000")
+ .toFixed(0),
+ );
+
+ return (
+
+
+
+
+ {/**Stake action */}
+
+
+
+
+
+
Staked PZM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Cooldown period
+
+ 20d
+
+
+
+
+
Claimable PZM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
PZM per month
+
+ 0
+
+
+
+
+
+ );
+}
diff --git a/api3-aave-ui/components/stake/StakeHeader.tsx b/api3-aave-ui/components/stake/StakeHeader.tsx
new file mode 100644
index 000000000..709ff4812
--- /dev/null
+++ b/api3-aave-ui/components/stake/StakeHeader.tsx
@@ -0,0 +1,51 @@
+import { useMediaQuery, useTheme } from "@mui/material";
+import Pane from "components/pane";
+import React from "react";
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+
+export default function StakeHeader({ tvl, stkEmission, loading }: any) {
+ const theme = useTheme();
+ const downToSM = useMediaQuery(theme.breakpoints.down("sm"));
+ const valueTypographyVariant = downToSM ? "main16" : "main21";
+ const symbolsVariant = downToSM ? "secondary16" : "secondary21";
+
+ return (
+
+
+
Staking
+
+
+
+
+
Total emission per day
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/api3-aave-ui/configuration.ts b/api3-aave-ui/configuration.ts
new file mode 100644
index 000000000..61b8bfaed
--- /dev/null
+++ b/api3-aave-ui/configuration.ts
@@ -0,0 +1,152 @@
+import config from "deployment-configs.json";
+
+import { zeroAddress } from "viem";
+
+const deploymentConfig: any = config;
+
+export const populateChainConfigs = () => {
+ try {
+ let config: any = {};
+
+ let currentMarket = !deploymentConfig.currentMarket
+ ? "aave"
+ : deploymentConfig.currentMarket;
+
+ const _deploymentConfig = deploymentConfig?.[currentMarket];
+
+ if (!_deploymentConfig?.config) {
+ console.log("using default chains");
+ config.chainId = 421614;
+ config.name = "Arbitrum Sepolia";
+ config.rpc = "https://sepolia-rollup.arbitrum.io/rpc";
+ config.nativeCurrency = {
+ name: "Ether",
+ symbol: "ETH",
+ wrapped: "WETH",
+ decimals: 18,
+ };
+
+ config.explorerLink = "https://sepolia.arbiscan.io";
+ config.currentMarket = currentMarket;
+
+ return config;
+ }
+
+ // read generated configs
+ config.chainId = _deploymentConfig.config.network.chainId;
+ config.name = _deploymentConfig.config.network.name;
+ config.rpc = _deploymentConfig.config.network.rpc;
+ config.nativeCurrency = _deploymentConfig.config.network.nativeCurrency;
+ config.explorerLink = _deploymentConfig.config.network.explorerLink;
+ config.currentMarket = currentMarket;
+
+ return config;
+ } catch (error) {
+ console.log("Failed to read deploye contracts file", error);
+ return {};
+ }
+};
+
+export const populateAssetIcon = (symbol: string): string => {
+ return "/images/logo-icon.svg";
+};
+
+// populate aave market contracts from deployment-config.json
+export const populateMarket = () => {
+ let contracts;
+
+ let currentMarket = deploymentConfig.currentMarket;
+
+ const _deploymentConfig = deploymentConfig?.[currentMarket];
+
+ if (!_deploymentConfig?.["deployed-contracts"]) {
+ console.log("using default contracts");
+
+ return {
+ POOL_ADDRESSES_PROVIDER: "0x07E8Be3643A4CAbF17a06bA28057DaC550Be4DaB",
+ POOL: "0x2eC72aE78aa2443a7BF8fA3252919a8727266CaD",
+ WETH_GATEWAY: "0x532D1953B697cfed8fE11fBb83f349B2849313e4",
+ FAUCET: zeroAddress,
+ WALLET_BALANCE_PROVIDER: "0xdaF92e3b1a93e0B70Ffd2710013F3D889155af37",
+ UI_POOL_DATA_PROVIDER: "0x925eFE8Bd5b492Fe843e824b098958419ec37b62",
+ UI_INCENTIVE_DATA_PROVIDER: "0x97AC14EF3C5792658640d5680A85673BE25BD3F8",
+ };
+ }
+ console.log("using cli contracts");
+
+ // read config from cli
+ contracts = _deploymentConfig?.["deployed-contracts"];
+
+ const market = {
+ POOL_ADDRESSES_PROVIDER:
+ contracts?.LendingPoolAddressesProvider?.custom?.address,
+ POOL: contracts?.LendingPool?.custom?.address,
+ WETH_GATEWAY: contracts?.WETHGateway?.custom?.address,
+ FAUCET: zeroAddress,
+ WALLET_BALANCE_PROVIDER: contracts?.WalletBalanceProvider?.custom?.address,
+ UI_POOL_DATA_PROVIDER: contracts?.UiPoolDataProvider?.custom?.address,
+ UI_INCENTIVE_DATA_PROVIDER:
+ contracts?.UiIncentiveDataProviderV2V3?.custom?.address,
+ };
+
+ return market;
+};
+
+// populate aave market contracts from deployment-config.json
+export const populateCompoundMarket = () => {
+ let currentMarket = "compound";
+
+ const _deploymentConfig =
+ deploymentConfig?.[currentMarket]?.["deployed-contracts"];
+
+ if (!_deploymentConfig) {
+ // return a default contracts
+ return {
+ fauceteer: "0x1591D0b23174d874eA3c00A401Ed40B8f6f406e4",
+ timelock: "0x529b627C260812b29f6a282345E5B140f1f7A927",
+ COMP: "0xa00C08439595a685b3696CB322F3FAAdbd4F4eD0",
+ "governor:implementation": "0x8c7fba1C054bAE7745feC3ee8E2486deA78d57A7",
+ governor: "0x4D87F098a261FE0537Da0bCfE2D9c74a05F94F56",
+ WBTC: "0x87ea1Ba65F51b96Cc5aebE8cf3Ef6377F3E48ef7",
+ WETH: "0x8F7863D888752cb312385433f9caeA921217B7A9",
+ USDC: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
+ cometAdmin: "0x2fBe3d5Cba1A43804c1365db89ba76397673A76b",
+ "comet:implementation:implementation":
+ "0x472A828d413caac050b39E05CC3E23713d694F50",
+ cometFactory: "0x5D777A696CC1853a431C8D6A6a6e173304C6DaC4",
+ "comet:implementation": "0x17B92aD13924C377Af1915d60Fb35bF3DDe77ed1",
+ comet: "0xf1321d893722b66680Ebb2CA56Ea0549A6557e74",
+ "configurator:implementation":
+ "0xF13f86a8100BCBA5C1b1EAa21e3A8847fD3d89A1",
+ configurator: "0x6bEf3B20d32E1dce94A1f2dFC2391f90887d4fE0",
+ rewards: "0x0A8c044ae869a509AF681c2ba9e0f3561f230e02",
+ bulker: "0x77c9Fe5a6721A3bC8DDbD1AE271cef58a1efE9b3",
+ priceFeeds: {
+ COMP: "0x302C053a2139Ee9028b500E7da056B6b4169B4Fa",
+ WBTC: "0x5EF17889992f6d9daCEb03db9822AA5b6fDd6713",
+ WETH: "0x132e2459498CFfb3f767d508066bf1dF0549D59C",
+ ARB: "0xf689D4e1d0B5B7281974389a58D65DE4722f046C",
+ USDC: "0x683Ae71AFB633385e64a7968435210d1aadbe29D",
+ },
+ marketAsset: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
+ };
+ }
+
+ return {
+ fauceteer: _deploymentConfig.fauceteer,
+ timelock: _deploymentConfig.timelock,
+ COMP: _deploymentConfig.COMP,
+ governor: _deploymentConfig.governor,
+ WBTC: _deploymentConfig.WBTC,
+ WETH: _deploymentConfig.WETH,
+ USDC: _deploymentConfig.USDC,
+ cometAdmin: _deploymentConfig.cometAdmin,
+ cometFactory: _deploymentConfig.cometFactory,
+ comet: _deploymentConfig.comet,
+ configurator: _deploymentConfig.configurator,
+ rewards: _deploymentConfig.rewards,
+ bulker: _deploymentConfig.bulker,
+ priceFeeds: _deploymentConfig.priceFeeds,
+ marketAsset: _deploymentConfig.USDC,
+ };
+};
diff --git a/api3-aave-ui/deployment-configs.json b/api3-aave-ui/deployment-configs.json
new file mode 100644
index 000000000..e04abe2c3
--- /dev/null
+++ b/api3-aave-ui/deployment-configs.json
@@ -0,0 +1,50 @@
+{
+ "currentMarket": "compound",
+ "compound": {
+ "config": {
+ "baseToken": "0x149e2e6348A7641373C4288fc6065446c99e87F2",
+ "network": {
+ "chainId": 11155111,
+ "name": "ETH Sepolia",
+ "rpc": "https://rough-damp-scion.ethereum-sepolia.quiknode.pro/cc005555675ae91caad17e851ac5061e12d61f4a/",
+ "nativeCurrency": {
+ "name": "Ether",
+ "symbol": "ETH",
+ "wrapped": "WETH",
+ "decimals": 18
+ },
+ "explorerLink": "https://sepolia.etherscan.io"
+ }
+ },
+ "deployed-contracts": {
+ "comet": "0x606720e0109Da235c31CE7eF60ab2B6a2C7c4d65",
+ "comet:implementation": "0xc20D7de5D219776388313bb0B0Cd98990b7ee4C1",
+ "comet:implementation:implementation": "0x087DF2F83b5AD3E5b1c611D015385b47688d9B80",
+ "USDC": "0x149e2e6348A7641373C4288fc6065446c99e87F2",
+ "USDC:priceFeed": "0xB16d6e5b8FA4F7D30C80625f00fA7cc03C15D093",
+ "COMP": "0x748293ed983964255E68ffc54b60fc09C7A53D70",
+ "WBTC": "0xc311e1B80702477831dac8c42D62757cf0E5D94e",
+ "WETH": "0x896B2aD8DfB1719E239E075C0C271E5547b23Cbd",
+ "COMP:priceFeed": "0x647543D606C03fF5e2B0EaB90cABc154d8799c66",
+ "WBTC:priceFeed": "0x46D41173310c8DE12f478C6151626A316AfE7de3",
+ "WETH:priceFeed": "0x4381865577687d8b61bbC8369Fe8BfA1bb6B3D54",
+ "cometAdmin": "0x81b11367C34B7bE3603CB13b2dfBF6bDE85186c0",
+ "timelock": "0x2b1062cc72Bdb50c9aF60dB4EA49377b0C00831e",
+ "governor": "0xa15259712Dd58D80f6aadB22189a2624Ee05C09F",
+ "governor:implementation": "0x3CAA666514d17D22Ae2fC169e879B636400fB7d6",
+ "configurator": "0x639e76Fe741174F0b465bf745999a39F4DA3CaBC",
+ "configurator:implementation": "0x2E39530015E8Cf8E4AdE4EE7993BE1A39cfD2B9e",
+ "configuratorAdmin": "0x81b11367C34B7bE3603CB13b2dfBF6bDE85186c0",
+ "cometFactory": "0xD802E2565b37A06F981b112595240Ee00E1A7a41",
+ "rewards": "0x84554b6EDa9EA2e33b1E615850f842Fc72b1049d",
+ "fauceteer": "0x8E1AD0BE8314FEE7054b51d3c684f17cc57720aD",
+ "bulker": "0x26eb67f98d02B9B4FA5A53cB77976079A0712598",
+ "priceFeeds": {
+ "COMP": "0x647543D606C03fF5e2B0EaB90cABc154d8799c66",
+ "WBTC": "0x46D41173310c8DE12f478C6151626A316AfE7de3",
+ "WETH": "0x4381865577687d8b61bbC8369Fe8BfA1bb6B3D54",
+ "USDC": "0xB16d6e5b8FA4F7D30C80625f00fA7cc03C15D093"
+ }
+ }
+ }
+}
diff --git a/api3-aave-ui/favicon.ico b/api3-aave-ui/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..c7e8bc45cba5b127df79f0cfab2f9561c2929152
GIT binary patch
literal 270398
zcmeHQd5{&=xgQgYSQJ&SilSaoiVT~`CY!^i=&*|z+2r_KLssbVmFbd3!OB4|_
zMooB;AR>YxaTtAh6{6$?O^Wb%h7iq@VNBJlvi!sH56Ysfci#8wxjppl+uQBir;
zOr5&-_UZ0(zUB9w?K|HoD!PIG@pnT}m!e)>ZY=s&`rfPMLQ&BVTCU?K|Eb4;=7!q#
z&5iW~n@`o1QL3a=O=%yc!;~5+ou%|CrDjTBQTmqBRZ7B?a1D952lwI`Jd1bWU3)3v
z-ODMJqs%WG>)WfxQKpDF5HAi8#&06bl~7ttX*Z=~l+IE5hLRb_VgE)Q&Qm%{sg_d3
zl~eVD>9cLTxX86(4#b}WR~l;D5q3sV+Dz#PrAw5qQ3@N^g_id{)%hYN&_J}*kD=5q
z{u1CCG6%xr0AZserMZ;$Q$jnMM67$Y6`&3M7SIZsJBG(;E{Qo1JqMcKf2u9%eL1DQ
zlrYBjiX9d2)B6bEMHwaTA4IRBT!Vl)aOG58C(`XTlo}{qrKBR3gP;k#X{1y|V}(uu
zi-BLq90-jAq{E#lZJ~rYbhL9p;3G}%0MEcX@UU}eg5!di13o!GdfJ{6wOw^*C^6=P
zvw7epcv?kk3mtrlhaY1O1kQoWr|Nz{dWo?s*5tmUl%_U13R=Nq@Ve~FQ*}26E>M0U
zbHD=!XiR@I>EI4ZUr>qy2V7>0pVAJJ1+OD`&{@8va1IdGhf_L4iQD@4*gdQ(!bfp<
z;S%OIFbA?Zkm=)3C;h@0l-u2S^8hlMcKJk2wh;Ljb0AL+kl*c%q)YI*P5U~15^dfk
z$d2a-@>F`hy@>Rt4W*TonkXev_qop3<@OoLknI5D+LZ&De*Rq27w8OQNG%>fri=cU
z)@xi9fp1712S_(2QM$mmSKjVnkHw_aDL4~s$pKnB>PPy}$hcP?_vZfG2PE_UmP)}F
zmFEEAz5~f0`_R}=Ppy8w8Rt&FuVr+AxPOefHARru*%`K}TvR4pW=-Aw@lk
zNtPv)cwV1zpRYZD&XlN!h;&et@!jJ#pK+fr?v3|jez1mp2$N+qNM=1LA$EjOmi(Rh
z;a3MfAzkW`EEJ@(wj`%Tl)h!`v+WC52cT1n(uu10Q%&8H&Nb=nbI=|NdMDJ9&`q{RJw#(vl~0y;M{o~Tg2
zRvACOT9N_#?=tqo#=c%2bg!286ozYWi0ADn9jBzrfj^lSQR=`+8V~T???Uy???sz`+KP+|>r^RhctgEL)=v@VbD(2GII`
z1z{iSB}N|ccjkwxIsjegSR!Nth!61VW8WUex~f>WqYFBpYCpk@KR^5QGWP8-qWbl3
zDYj@T_Y08i!#+OV%fr}L9pi5F0RySpH%PI$v45ZU@G|z@u#uL0U?COp12S=YP7=Lo
zkuB57vi70_$I}o;h;WaXU0(RX_b{K*rUSKxWijQx67CVJlh^qe*J;DGS9*aBC1Z-x
zTt8xT^ISh;-zyfwe!dt;`~3%1
zm;fN`BX(EXWy$oj4*1c5MEeL6?t4(;F+c0RAKm9?TCmeIiTwbanNHZpxydX?<^k(~
ze;qh`xuN#Pq}c$%J;(3zFLTBV^UkOPJCcNd!hQ**Yuxs8--mS|5FNl?!IC7{09xy7
zLv_8tat}oA#x{Vzr@K!8Otp!-4WK%5zdzl2%63Yg{9`>1Anf;}#IZc&$)B;6Zr%c0
zed5>$xO}1pv3$-@VjX23unx%6fe+)jPmpk5$=GMx$2t&-4phde4?uf++LPSBX4!`#
zdv06hwXI3v?N@}g4so#oRG0mXea1fPK&U#fKMwdOnfIr}YyA=TqVo<-HqStNRMAt5zMW;@;h?{S|SxcR6xkYp-
z?yThv?Aue^UD8iXy!TEqm!4fYXS~?Ha+-MY@e1+wv#Z1(4n8I>zqcnTZKUe;M67^*
zQQH8j!v~a9=XGr8`|CS3;`no`MeX`o;-ML%#i-!}H2ms#mi>9_t)0Y(JNt?S_ur%0
znL~BU#JM-CW5b`6>0)D)_$OXZN*TXH*Ym#|*)CqISt6?DP0-qAwAW4;zqL~*t*xIh
zaAJ(+_h9(I`L%ab~7aG#euF1QLG0Ne|cYjK-dT7Pwrc*joJJ4
z>XCyfwE3fk4bX6hzQ7-Uu_ZR`D{Rie-Al#BCHIN3cMlSsX?$R|Rb4vYDrQc+OY3V~
zJpM!+Fr!)>=7!k^$n5R?EJZd}ioTqE<8e{FVw%=>He;rL@7u(R+2b^9{rB5DrIas2
zet#o;zxmV(vQ?ACut9xtZ9(y^+S~!|khGu
zwTI@hJm%=pj=r~ly}*4c@c5&jZ5B_inL+)R{yDY)^zK;ofH-%A=MMvr^~x~%0NnQb
zo7eiEU+)(CXdMl6=f<|aN4G9oJCFXqDwwy^Wvm~fztgjOmng
zHNXFq^f)0@7PtL*jQfFm%$W`9cYBu3!v^f4b}?;pW2ax+=(wJMdBg2wBe+lC%N8t_
z*$2q%@wsGY-}(A=nV~Jm+L{&a_4a@Chymil(H%cBb16UdvI6d3f8rr+t=>t$^}HbidW$pEFOHh87=OIGca79~
zJn~?fC+zFI!6()~;m7#fS00gCx2X9aVENN!^#Q1kyua6>?~i#s_|F>k*UNXT<-@-=
zKpn{IUHi9I2+TzyVT>-L93$EDOy2F($@^NbAq6D`9dq9^w9
z{^;kM#RKDq=Z$-#-UEA>3lDQm41JZY%cr!~`_BHo1lI3@mNWVmU1;6UNUz`T#pFxy
zc;yuF*{^m5UeBQEj_`fMgSG)g%i##=iKVRnadNlVwtT99PWshn^K;mH1A8Ky*VspZ
zJwAH*_YUn(K7QK*FZa}e4LS4udYOfM4kCZ!!}ZGpudi&rhxGnKLE@kG_jjav^BzA#
z-@oyt4LNIhh3K>KS=bZU6cdO0#amrNfmE=s6-
z(7XuweTWlwb5J&b-nAp-`UkFyLDe69X85xN+2-5f0zQDxJTgaoelnQ8F6J4r&aRh-
zF~`lP|1|t|h^`{kTfNFUK#R-hcUFv94lLtoQ>TBaTU;
z`Jx>w1phSe*Mal`a|yonBk9k+L@_eL8pk@}Rc2l{iV1fAn4w}b#r}9@$70cNV7;~$
zV4QzMn~J_Ye1s4~q;lq1&F09gS0V4lTBa;th6L#}u-o3R4WMVM5=3j@HVS%v#|;kv2<@Sj?LKVZKQf3-05o6B&wEr@ygyH_^`-ZmttUG(J-Nc454
zgczf#;~nUJc#NPg5k6F~~S3&ALzbm^B1K(=+Y^P1HiQcpM;J^7)eJ6S*RegW#
z!;i!IK4Uf;vqAG?`RuW2#6Pgy$*T>Zds8*<51-zth-JK~UKz3rJy=c8l(Hw`*ZG=A!Yf6DJjDHZE}
z#@JVk!{~7sr3`+$b8%Ym4>~*A*#OF$OG$ZNU=LfA`o?9)%iiFOh7`>O+MX3k*x#Q9
z{KF57F&HllMlFx0Db89NbRQUZX#dZt&I820j9S;Y{P@`(>=ib~J5U%0=dJKhKEGJ^
zS3bsX`RE~x|CIRoiyjIzN0X4UbJ7`U=@hu^D)oj_bw)p0=dZMMMw5tZrw%aQGO!A~kZe0JW$e&2
z;QxpP{+0Iosa-#d+kPJRyXpYqJ)TwnjL}O*{5Ln$wxzaTX}_P5KF;OkwmjKwxnKG1
zB)@Q#`@%%qwdTh9n{*pMalQwuOfP)A{ptcgmp&UXd{7_N@ele+bo|rz3YGD1JmZ@2
zoIX7Jk@>&>ZK5
z-^(+zCf~&|10$SMteQ7obT*u6>P2Q=?}0zy<@ffeYy(=)1|#gBR~7$1-Z)Ph{(rLl
zLG8?0uR6u|1=n9d%%+birvEgFaU0)$c9qKbKWAwFzfl$cvnSsz1^>`L#FPK@*iMca
z9zh?VV#>W5Hf7rP)$=E)jQ?+df5LrxRk4q=uzPmzDh2;#qe@zJW7XX8Qp(`|f_;DC
zSG0#4di$qeZj*La(?B{S`AUP*`{CQuI^aN6@qg;T25Go7?iWQYS;ne8R)gkE>9GE-
zwimiPYWM(Y{8u?X*p*Wn_RCep|E@JNr0E6XhZ*^X^Rt82bAF$-P1(P-B8&GmRr2CE
z)@_)bRhCia3VcVb-{lI>VJV~O6NXE{oAfCo=O4a}C%(%6QGjYta1IQh9$4?;#6W
zXSdznqpQk$f`NS{<9&blv(3`5*!a>0OC97rMsl%_HJ3mAa;qipA0~gDplyx*zTdyT
z$+Apy8<4=?`>4)`6IgFoc_5~%F25i@2RO_L$7wAPvF+i*GIU^XZGLRR$iV`!kEVUXL
zt^xZ>p7po+p>iqu;I<|VpEN(Z?e&?iT{?@q?(C=Gw`$%5fw`|2AFmK^)~^ugm%u0H
z(upSn*H?_EE*^hEd~#^3z&Yvf{J2WIN;dWxikk^uFP$+)voAvi^p@t6ck+d`wsgT)
zuh(ter11Wc2g_{BO}GsJ_Rl7q220ss-o`7Y^108=C+zfV!K?*h?HTizk1oDX!#84<
z|M~E?M65?+E(CT6HUj=RYZpw^`W1!D$6$@mO;49hA1y`Z@G*2NJE8f&{-+78yQ56d
z@689-UheJDt&68P@l*0#3migqeQ??+fwd;|WB>Y2jU#PIl^1+z&XQd?xNE6+Z0Y@4
zf1w-oXT0$Kz}AJXJUO^~si${&DbIKhY;jU~?ow}HzuD!U#L@o6Z}x~=CF~1XG_}+d
zFAzh{s6WQ4B`^r-ixG852iX`cn7l**#~?
zPk-L{iE$6k_BQf6i0{~EsAz0(VE-#44^{a7$6ss-TnC^>uhlH^gjI}{jcb7z6R)e7
zq~RT7Xcc%Yiw2y-gRu_g6!d-Dk5}fdx7w9IbE2Ga-)S}10KO(Zerw0eq+XYCz8ChH
zUd*Fk4qH)2ZQ4ga-^_R~;7qwQw0|4>ti0;tzAX!+*#5VkUg^0GUh5iz`+)tcF{nqN
zyao1x==T}lF;(3;pg?&awJx1|vs%hprI-1KsA>06zH-#BLDZF^}zozx+%A
zZNFcB!`C4QnH%4+d+kh?WdySHqXXNPPYqQ5nE$~(Q$Ka#XTsk_=U2=b$M{c3`ww3@kNC_R8Jm{WGQ
zw7N#fUtnLk^}ir|e-Ym+1u@`N)afjmjy|(e!2iPBp6B};d!{19sjRYrefR*#dVeJE
zg{<%@NY{oO%la$zq7cwD_=s(60$e9c$di$4{7_b?|^$aw*Z;vc?$%K88L#s9>6
z@3h@tuIn`R*sWhUSq$!XyC)liJ-C%K$BJXL7lv(tdpiRk-hEptw7A|~Xb-b)m+d|=
zM#Fw(_*&tNXI)NKpNH$0``#m{DE@(c<@W#h!9Usu_?}wn4X&XdS?Id*-E;;i_RO*!
z$h8C5^Mu$wh&5n`b+_xV7t3aibzG~({v*UTaC?_IUs3!6`^xSA&Bq5E?Z>kl=i1^P
z{$!Z@G3!Gizb8>Y17ia_Ta&iyuk2VX`u6G`7>}{1a2NUOU>~v-FaQ4TlVT?AHOfbZ
z^UCkBe3#Yx6LbyOS1$esWaUM+*eizdyPdqyXUE<%FYn6t9_XmTab;|IYUK4lPVUy$
zSMueZ*Za#x4H4(xvK|w_HY}e#*0XF8TfkU%MZN?3%EkZk5(fgygUun*cRmi^v`eVFE0?K)qvPjkiWah~e1nqn>K&nff??C(>E9!*Aw
z(dDEsz%}NA?C5@}dXbbpBzAS$zH*vvUF_9(@*!ly#+S^U7LthyNW0Jh;SvJrOgSJXZ)Cm!GoAX~m9F%Rv#l^o&I=X9n!
z;!9gS7uL10G#*C#m_(j?sWa>w;;4khPpfjA=6kUw)4gl4W&IS5|52{u`JWiun`IBb
zKD)Ccpu0Fv*8EHqzcKIV1xrc12XS9MKZU*r{(nw9
zMf_NtpQM+AzN6Fq3C;Tk*vB8$|6D?8u#^k1uKSK-&j|=v$Yy#Pr5ke7;A2
z%|iKVd>-o%PJBhoVSO%8QQyC#2K?`K;zbhk^fl)9_OEx9vw2@A;(Zy%3)ll7<6H@&
zKAOMVoiUt5Szynuk-m{b?#S}ZH)73rpUm%G;yLSQIX1C{k_^TksS&&j%GMI++6n|0~qH*(LIx4O^#T#&!>
zIrGMft~gyYo`nP+S?zt4ab|;?Jg^VYjZg3!L@Y74`x2NxxE22mwKq}yuO*NMTe;v2
zAe{$O6+YJKx}uLg5&ay~M^
zS>|rM+p}(#r9QYl7xVn@ubirDtK%P^RNqT6ud}PHjP>_o+i^ek-x+lVXYm@}qko6*
zknuj*-x0?`FFWaiR&`b2+7S!X^(5zQM{dV(N^g>%)?lG_bTdk+k_|>kn(_lER(0^cf0xj8Rf6o_j6X*&)|Q*Vzg%InH_EBwjFC!#L#jjU_z!>Z
zAlnze?;1+}2Tn1Hk}98u1M6eKU&sahjimCizd(mrC`ZKX3|UBfhv${H3-CdWD*kU*Iu9rv@qe@Zt&P}}{oN`4
zZ%TB&%#3&Q@8(nWZHX6GQ^JoNdv@aa)uGS#LGN+qcp7+){*4}+K{nov??;RmMPvAR
z)f-^ia@{}I2GljAK^N_44Ey{a_`cZHMaAnl>o@H4f8bxNA}{lxsnLvcyWjNAHF>;O
zNxs4cgmDf~+OV(dRhZ}hA)cpRZi+vv?C@^BPCV*F32OzZ<{Ny{WuE{0>dwWf=I`gf
z+9e*Mb9IgV^dP^Nm6iz1>7-qcTd-W;$&7QS-}DU522VZja32}7{IJA*q66q;bdXl)9$3N
zXxCQE87Gd@x`N7U`({4*{f)f>@Xy2kJpBv@C;s9r_lfrm7IoC#pMPt+(ru7Wo&v+2
zov?0~N6(${S!OEafcSBUZD0TJY;B(a_POHhap>Z~T}#E8pKn$%c3fz({ru!Efpf!P
z4-lvAQ98RBJjR}Zy^qZoSgXZa0_&*bIQ@(rzTK`9U#pn6j=W{vv*^pS&csS*JkR@^
z?E%RVXM=vn@{E-{+2*j#@u~ygQCy!6W?bjkZhAF+LL4l{gs?jJK$;2Z_3^A%aQ0_|TO
zcEfYN`6Qp=ETceWq}eLO#DRaHIW7)-g;nquG@q{mJ1~4uAMwIt3k3Q)tW&}36tJ2v
zzP;Q}?`40$0LB1l|8U001LKDa#KN}nZ$(U8#3fETKGs!CvZN0*_wLzE^W{5tq&o3*
z#z;=S{r%i*0MR%-Msy}lXApN1V|(*?BS!pVzW`za;9MeAc#XXevnSu3bIy`ZH*DSV
z*<(eDWAXuGK{_M4ws3ruBv;6ktnEaSWxr#-Id@59es<=C{?4^cI5f=R
z^}Wir#U4H&`uD!g(hh(xu!ra?@f<;3^8<^$V7QQb=KsoxkifM}WQ+;xVxw
zK`SpqYx@m0U~Zaq`40yl6KfYt6y3WP+v0u-`MbRN)QVJ%?Ss+@#9iFJa+>3uDg26X
zUYg2trXKmZNXKPZpP99Q3m)sIOuKi6a6h+fq~q9r>5MV#?`rDf`_&V~2!<~t&hOC2
z0_IQ5Bcc!Hw~T~8cV70Kznx7XzD-Iv@AB4}kLer<#GEthV6WS{X)(b5e0W>l?@SvH
z{m_fPKKfEq#tyTbBba;N$h7i(k{v$7xK6Tc^drwCKeNzqPAJanes0rz@%MM1OsoEd
zPB;97Drb(#@|iyQ!rIX55d$6mAPkHicVbHB{LfaV$!rc?XF!na#FwAZ);
z@$RdH@sDwnPTZ&<_pb?S?cH!0Wp=cG
zP?HA~Be|8ZkG%n@^9y8~$2MQG4qTwKeA+|;>O2c2K9o@6aX|j|o!dm_nUxM;t-mBs
z7)E+K)tAQstjkuq%-8bQi<(Hm?4$6@EpbB5k{w`qGY?n?{OiCcVa4_E0dvPk2>U%L
zeakk0Z6ND_FC74OdN_hC=9yIgMJ#(?vgbC_f19Za??T_#FTm?Xke3b|
zl!3)4-br$AONrx#b9<&ryDXcIPbtoB+bFOqt4zXwFG@TYz&1cOc9Q;nV5FBU97g$G
zqH89lRK*G)dXuh?T>tQ72yD!Z5~H%qCi-d_6KoS$2P}19w`}}H{r=28!Q(7{OZjtK
z8(v!*H(sBNDvoE^Hi59;j?#Iy0c-%pKUN@m
z-`6=xEJjr}#SI%wvgb8{^!9n<)&~!}KG6NaQQ%+Qysrb=$0ykUtPAkkAlrd3uo`3;&{>}6_knryBjg`YLA+!i
zA+`ZQ;#20kpsS0_dd$E5bAb2>KSA~tW*Zs;d>dX_0k=;)7f`~27=L@h6C=}CPpNFm~8KXNg5Eoc5&PyPf@Hss`8x9^A05Cs_C2k&
zjjzU$12{9CWL87z8ruQ3gFbZte!M%Vzkg#Kb)4(u&H<8N38f1@<)2R*!S|}wr-06s
zxN8{S5qA!J*;wC(WQo4ORkj1%7jV&mmNx%XU7NV;HP1(zF+!x5`z*o=-_Tx(uk_)RV`3$uuneV5>^MmPa
z@8Q1-9q3S)Hu2L*S<kWDI-kco_(1EgymDOFQyro>}|Xn62NMg})Wt`J;-RB|9QM^Hw3
zc#IO-A+`l_c>o@R*Ja$tPbK7HOEmcub|Ag1qJ%Lh$0ZHU4uF^7X%*R9_SK6m0=Qy2
z2S`_OPQeyRh#kSUAb(o`o`HAZA;;C%6^lO;$ARX?`c9<7=od6n;yuXrwg9|optOck
zr^E@GE6f~l;Q;kt+mUW#zF;qx!Tadn`aJXzr+#Fqs(UK!F@+K2?wY!5BDIKAd)II{Reknu4X8Ig;h0bj&
zkUji3b0BpbAndfIG?-EarCLfyDWM(xhEmk)ji>|qEm)J=O$qxZO33f_rql_F31$w2
z%mIpRh&Uz#DV0-NPN|yGUP|y$Y@~!abd0g#r}P!2Zz)}+WVRc)hCJMZd+`jO#XIn>
zeU$L-N=jvv1`@{GhfFRP7cd7z*57wUMa5YcvVVMo!v7`vn&H>~wbX5=;ZoMu(=GWw
z%({5}$M-GSMMb68uNl8J>G?l0UcLTZ&n_yue$DWWXw(0S4VPQLp4M}ViY#k*J=?MX
z!|N@X*kpX(f`S@j{td0Q(!XSQtKYO!zpj5~6>m|2CjH5l&zuU>WapbJU@E?-$W(z=
z+3Bw-)hpKWscDX$hfk9hoi^s-yGaB!=KSmm=2XvA!JO)ul+46E6jp2`pvhc(QBf8L
zPv_=m5m1wxZzRB?`dI{6R6mOVi|S_)ki&gc#~^{G-0Ec!c-ku8KwynkzJWliYy*fa
z$ukgWNuGf~OY#f^y5%=n*RNH=r>*l_8Bk-L-^u{%>{bR?N*~YcY*9fQ_Ovp{hCQte
zvLU~fL2mg?cJ2O1YpbF41;ai=bo=Y
zu*sf2jlpjDr|qBD1W;q2uL-~{-~RCy0l4Hlh({BETfT$%Gz7TiJBUvckXyckcr^sM
zq4|#L
zM+z!CzsXs?KZ-j4v~&G_76Y6i9|WwhYR!$Cd#Z_Sl+;V!eJg3@Fv}
zZ5Xgq&$nSfYqm85TFJLzKr8t+3}_|ah5@bQ+c2Q`di^XJPg8~-*z|g{6*U)c;!sZUrV8W~Z>m5}@l+jSGi0tEejChamhR~H8q8d=el6?s
zdI4FNTYog^H(1mjH?_*JwDpnfFPR!z)(&@OguFBRDZ?+VDK%-1AzNc&an=R#|Ce2M
A;s5{u
literal 0
HcmV?d00001
diff --git a/api3-aave-ui/marketConfig.json b/api3-aave-ui/marketConfig.json
new file mode 100644
index 000000000..3213f046f
--- /dev/null
+++ b/api3-aave-ui/marketConfig.json
@@ -0,0 +1,168 @@
+{
+ "LendingPoolAddressesProviderRegistry": {
+ "sepolia": {
+ "address": "0x7513fE9778D0c8B9a8fE4d05cB8cb5eE9E44c6d4",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "LendingPoolAddressesProvider": {
+ "sepolia": {
+ "address": "0x87b3e5AA46E88e70ad95331191A465CD048459dE",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "ReserveLogic": {
+ "sepolia": {
+ "address": "0xE63bc57CB8026D7419f1579AD83007E29009BC50",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "GenericLogic": {
+ "sepolia": {
+ "address": "0x0b6ACb73882981Cb8e60f124785Ea88CeEbBdDc2",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "ValidationLogic": {
+ "sepolia": {
+ "address": "0xc4B746CC5e0B4BE77452ea26651b27C6e39188eC",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "LendingPoolImpl": {
+ "sepolia": {
+ "address": "0x8B21452cCD97e94408d0d04C552114B0eCffCdd7"
+ }
+ },
+ "LendingPool": {
+ "sepolia": {
+ "address": "0x47d96F2718e7BcA8BdC94e4af225E67A6a0729f7"
+ }
+ },
+ "LendingPoolConfiguratorImpl": {
+ "sepolia": {
+ "address": "0x9435BEEDeF323aD4E331E9315C1E12AdF8f524Ee"
+ }
+ },
+ "LendingPoolConfigurator": {
+ "sepolia": {
+ "address": "0x67A0d0b2eb780a6A148Edbb9a07Fff02F2d68538"
+ }
+ },
+ "StableAndVariableTokensHelper": {
+ "sepolia": {
+ "address": "0xF5507fD6db89d0fcb3822E63ea9d166E0d5F7ae2",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "ATokensAndRatesHelper": {
+ "sepolia": {
+ "address": "0x696c76aCE1165107F1f8836CcD88f2b47b104A5b",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "AToken": {
+ "sepolia": {
+ "address": "0x80Fd16B6b989742c785A9D3276EaC7D46f51Cc7F",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "DelegationAwareAToken": {
+ "sepolia": {
+ "address": "0x03220133445046F4f910Ba1808F2b3e104c364c0",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "StableDebtToken": {
+ "sepolia": {
+ "address": "0x13818cd7253Fe4c228B7657CBF9278F14EF8f1B6",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "VariableDebtToken": {
+ "sepolia": {
+ "address": "0xb8452d850Eb685DDa68d3651c704e256c40759F4",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "AaveOracle": {
+ "sepolia": {
+ "address": "0x73740DC2b7bFDB0788fe1C250539765933B2CFeb",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "LendingRateOracle": {
+ "sepolia": {
+ "address": "0xAd07201C12011b685b38446540105509F0CfB27C",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "AaveProtocolDataProvider": {
+ "sepolia": {
+ "address": "0x7C4AF217bAB801002d8f6bfE5b38265eF9Ef3978",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "WETHMocked": {
+ "sepolia": {
+ "address": "0x619769eCF799101f4cfA656bb6B0452b052DE926",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "WETHGateway": {
+ "sepolia": {
+ "address": "0x5919331e01fd1208d41cE9937d530a161C146b33",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "DefaultReserveInterestRateStrategy": {
+ "sepolia": {
+ "address": "0xf842CAD4A0B4b23E5f3Ff24C92cD2CEdcacC069e",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "rateStrategyStableThree": {
+ "sepolia": {
+ "address": "0xE74b7d4c2F36E0c6D63C4bea0eEcf49400942309"
+ }
+ },
+ "rateStrategyVolatileTwo": {
+ "sepolia": {
+ "address": "0xd56ac130ca8d28B0C8f1443CE17aA68d0f4374b3"
+ }
+ },
+ "rateStrategyWETH": {
+ "sepolia": {
+ "address": "0xf842CAD4A0B4b23E5f3Ff24C92cD2CEdcacC069e"
+ }
+ },
+ "LendingPoolCollateralManagerImpl": {
+ "sepolia": {
+ "address": "0x0A9F130A825E7d63f1eC866C60d18059915288B8"
+ }
+ },
+ "LendingPoolCollateralManager": {
+ "sepolia": {
+ "address": "0x0A9F130A825E7d63f1eC866C60d18059915288B8",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "WalletBalanceProvider": {
+ "sepolia": {
+ "address": "0x245C93099B45F9AC4009eD1dFB5e910AE2093EF5",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "UiPoolDataProvider": {
+ "sepolia": {
+ "address": "0x7601C0Ae90EfB15102B0EC65b0f587D2fa675A40",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ },
+ "UiIncentiveDataProviderV2V3": {
+ "sepolia": {
+ "address": "0x07E1a2e29a67F5D632817BD2D556ac160A8F96cB",
+ "deployer": "0xa5b24D7210a78e1DC134ce062Ceb11bbB9e3DFF9"
+ }
+ }
+}
diff --git a/api3-aave-ui/next-env.d.ts b/api3-aave-ui/next-env.d.ts
new file mode 100644
index 000000000..4f11a03dc
--- /dev/null
+++ b/api3-aave-ui/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/api3-aave-ui/next.config.js b/api3-aave-ui/next.config.js
new file mode 100644
index 000000000..5612b85fc
--- /dev/null
+++ b/api3-aave-ui/next.config.js
@@ -0,0 +1,13 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ reactStrictMode: true,
+ webpack: (config) => {
+ config.resolve.fallback = { fs: false, net: false, tls: false };
+ return config;
+ },
+ images: {
+ domains: ["s2.coinmarketcap.com"],
+ },
+};
+
+module.exports = nextConfig;
diff --git a/api3-aave-ui/package.json b/api3-aave-ui/package.json
new file mode 100644
index 000000000..5f2d6e592
--- /dev/null
+++ b/api3-aave-ui/package.json
@@ -0,0 +1,54 @@
+{
+ "name": "phantazm-frontend-next",
+ "private": true,
+ "version": "0.1.0",
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "deploy-preview": "npx vercel deploy"
+ },
+ "dependencies": {
+ "@aave/math-utils": "1.18.2",
+ "@api3/logos": "^0.1.45",
+ "@emotion/cache": "11.10.3",
+ "@emotion/react": "11.10.4",
+ "@emotion/server": "latest",
+ "@emotion/styled": "11.10.4",
+ "@mui/icons-material": "^5.10.14",
+ "@mui/material": "^5.14.8",
+ "@paraswap/sdk": "^6.2.2",
+ "@rainbow-me/rainbowkit": "^1.0.9",
+ "@tanstack/react-query": "^4.28.0",
+ "@wagmi/core": "^1.4.1",
+ "apexcharts": "^3.42.0",
+ "bignumber.js": "^9.1.2",
+ "contract-helpers": "^1.20.1",
+ "dayjs": "^1.11.5",
+ "ethers": "^5.5.4",
+ "immer": "^9.0.15",
+ "next": "^13.4.19",
+ "prettier-plugin-tailwindcss": "^0.5.7",
+ "react": "latest",
+ "react-apexcharts": "^1.4.1",
+ "react-dom": "latest",
+ "react-number-format": "^4.9.1",
+ "reflect-metadata": "^0.1.13",
+ "rxjs": "^7.8.1",
+ "tiny-invariant": "^1.3.1",
+ "viem": "~1.6.7",
+ "wagmi": "~1.3.10"
+ },
+ "devDependencies": {
+ "@types/node": "^18.16.12",
+ "@types/react": "^18.2.20",
+ "autoprefixer": "^10.4.15",
+ "eslint": "^8.15.0",
+ "eslint-config-next": "^13.4.19",
+ "postcss": "^8.4.29",
+ "prettier": "3.0.3",
+ "tailwindcss": "^3.3.3",
+ "typescript": "^5.0.4"
+ }
+}
diff --git a/api3-aave-ui/pages/_app.tsx b/api3-aave-ui/pages/_app.tsx
new file mode 100644
index 000000000..8dd63fd0a
--- /dev/null
+++ b/api3-aave-ui/pages/_app.tsx
@@ -0,0 +1,87 @@
+// @ts-nocheck
+"use client";
+import "../styles/site.css";
+import "@rainbow-me/rainbowkit/styles.css";
+import type { AppProps } from "next/app";
+import Head from "next/head";
+
+import { BackgroundDataProvider } from "src/hooks/app-data-provider/BackgroundDataProvider";
+import { AppDataProvider } from "src/hooks/app-data-provider/useAppDataProvider";
+import { SharedDependenciesProvider } from "src/ui-config/SharedDependenciesProvider";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { ModalContextProvider } from "src/hooks/useModal";
+import { SupplyModal } from "src/components/transactions/Supply/SupplyModal";
+import { EmodeModal } from "src/components/transactions/Emode/EmodeModal";
+import { GasStationProvider } from "src/components/transactions/GasStation/GasStationProvider";
+import { Web3ContextProvider } from "src/hooks/lib/Web3Provider";
+import WagmiProvider from "src/hooks/lib/WagmiProvider";
+import { BorrowModal } from "src/components/transactions/Borrow/BorrowModal";
+import { RepayModal } from "src/components/transactions/Repay/RepayModal";
+import Layout from "components/Layout";
+import { StakeModal } from "src/components/transactions/Stake/StakeModal";
+import { StakeCooldownModal } from "src/components/transactions/StakeCooldown/StakeCooldownModal";
+import { UnStakeModal } from "src/components/transactions/UnStake/UnStakeModal";
+import { StakeRewardClaimModal } from "src/components/transactions/StakeRewardClaim/StakeRewardClaimModal";
+import { StakeRewardClaimRestakeModal } from "src/components/transactions/StakeRewardClaimRestake/StakeRewardClaimRestakeModal";
+import { WithdrawModal } from "src/components/transactions/Withdraw/WithdrawModal";
+import { CollateralChangeModal } from "src/components/transactions/CollateralChange/CollateralChangeModal";
+import { ClaimRewardsModal } from "src/components/transactions/ClaimRewards/ClaimRewardsModal";
+
+export const queryClient = new QueryClient();
+function MyApp({ Component, pageProps }: AppProps) {
+ return (
+
+
+ API3 dAPI demo
+
+
+ {/* TODO: Fix the favicon */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default MyApp;
diff --git a/api3-aave-ui/pages/asset-detail/index.tsx b/api3-aave-ui/pages/asset-detail/index.tsx
new file mode 100644
index 000000000..32f8562ce
--- /dev/null
+++ b/api3-aave-ui/pages/asset-detail/index.tsx
@@ -0,0 +1,501 @@
+import { useRouter } from "next/router";
+import { ReactNode, useState } from "react";
+import {
+ ComputedReserveData,
+ useAppDataContext,
+} from "src/hooks/app-data-provider/useAppDataProvider";
+import Image from "next/image";
+import Link from "next/link";
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+import ExternalLinkIcon from "components/ExternalLinkIcon";
+import { useWalletBalances } from "src/hooks/app-data-provider/useWalletBalances";
+import { useRootStore } from "src/store/root";
+import { useProtocolDataContext } from "src/hooks/useProtocolDataContext";
+import {
+ getMaxAmountAvailableToBorrow,
+ getMaxGhoMintAmount,
+} from "src/utils/getMaxAmountAvailableToBorrow";
+import { valueToBigNumber } from "@aave/math-utils";
+import BigNumber from "bignumber.js";
+import { API_ETH_MOCK_ADDRESS, InterestRate } from "contract-helpers";
+import { getMaxAmountAvailableToSupply } from "src/utils/getMaxAmountAvailableToSupply";
+import { amountToUsd } from "src/utils/utils";
+import { Box, Stack, useTheme } from "@mui/material";
+import { AvailableTooltip } from "src/components/infoTooltips/AvailableTooltip";
+import { CapType } from "src/components/caps/helper";
+import { GENERAL } from "src/utils/mixPanelEvents";
+import { WalletIcon } from "src/components/icons/WalletIcon";
+import { useModalContext } from "src/hooks/useModal";
+import { useWeb3Context } from "src/hooks/lib/hooks/useWeb3Context";
+import { populateAssetIcon } from "configuration";
+import SymbolIcon from "src/components/SymbolIcon";
+
+interface ValueWithSymbolProps {
+ value: string;
+ symbol: string;
+ children?: ReactNode;
+}
+
+const ValueWithSymbol = ({ value, symbol, children }: ValueWithSymbolProps) => {
+ return (
+
+
+ {symbol}
+ {children}
+
+ );
+};
+
+interface WalletBalanceProps {
+ balance: string;
+ symbol: string;
+ marketTitle: string;
+}
+const WalletBalance = ({
+ balance,
+ symbol,
+ marketTitle,
+}: WalletBalanceProps) => {
+ const theme = useTheme();
+
+ return (
+
+ ({
+ width: "42px",
+ height: "42px",
+ background: theme.palette.background.surface,
+ border: `0.5px solid ${theme.palette.background.disabled}`,
+ borderRadius: "12px",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ })}
+ >
+
+
+
+ Wallet balance
+
+
+ {/*
+
+ */}
+
+
+
+
+ );
+};
+
+interface ActionProps {
+ value: string;
+ usdValue: string;
+ symbol: string;
+ disable: boolean;
+ onActionClicked: () => void;
+ reserve: ComputedReserveData;
+}
+
+const SupplyAction = ({
+ reserve,
+ value,
+ usdValue,
+ symbol,
+ disable,
+ onActionClicked,
+}: ActionProps) => {
+ return (
+
+ Available to supply
}
+ capType={CapType.supplyCap}
+ event={{
+ eventName: GENERAL.TOOL_TIP,
+ eventParams: {
+ tooltip: "Available to supply: your info",
+ asset: reserve?.underlyingAsset,
+ assetName: reserve?.name,
+ },
+ }}
+ />
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const BorrowAction = ({
+ reserve,
+ value,
+ usdValue,
+ symbol,
+ disable,
+ onActionClicked,
+}: ActionProps) => {
+ return (
+
+ Available to borrow
}
+ capType={CapType.borrowCap}
+ event={{
+ eventName: GENERAL.TOOL_TIP,
+ eventParams: {
+ tooltip: "Available to borrow: your info",
+ asset: reserve.underlyingAsset,
+ assetName: reserve.name,
+ },
+ }}
+ />
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default function AssetDetail() {
+ const router = useRouter();
+ const {
+ ghoReserveData,
+ user,
+ loading: loadingReserves,
+ marketReferencePriceInUsd,
+ reserves,
+ loading,
+ eModes,
+ } = useAppDataContext();
+
+ const { currentAccount, loading: loadingWeb3Context } = useWeb3Context();
+
+ const underlyingAsset = router.query.underlyingAsset as string;
+
+ const reserve = reserves.find(
+ (reserve) => reserve.underlyingAsset === underlyingAsset,
+ ) as ComputedReserveData;
+
+ // user info data
+
+ const [selectedAsset, setSelectedAsset] = useState(reserve?.symbol);
+
+ const { currentMarket, currentNetworkConfig } = useProtocolDataContext();
+ const { walletBalances, loading: loadingWalletBalance } = useWalletBalances();
+
+ const [minRemainingBaseTokenBalance, displayGho] = useRootStore((store) => [
+ store.poolComputed.minRemainingBaseTokenBalance,
+ store.displayGho,
+ ]);
+ const { baseAssetSymbol } = currentNetworkConfig;
+ let balance = walletBalances?.[reserve?.underlyingAsset];
+
+ let maxAmountToBorrow = "0";
+ let maxAmountToSupply = "0";
+ const isGho = displayGho({ symbol: reserve?.symbol, currentMarket });
+
+ if (isGho && reserve) {
+ const maxMintAmount = getMaxGhoMintAmount(user);
+ maxAmountToBorrow = BigNumber.min(
+ maxMintAmount,
+ valueToBigNumber(ghoReserveData.aaveFacilitatorRemainingCapacity),
+ ).toString();
+ maxAmountToSupply = "0";
+ } else {
+ maxAmountToBorrow = getMaxAmountAvailableToBorrow(
+ reserve,
+ user,
+ InterestRate.Variable,
+ ).toString();
+
+ maxAmountToSupply = getMaxAmountAvailableToSupply(
+ balance?.amount || "0",
+ reserve,
+ reserve?.underlyingAsset,
+ minRemainingBaseTokenBalance,
+ ).toString();
+ }
+
+ const maxAmountToBorrowUsd = amountToUsd(
+ maxAmountToBorrow,
+ reserve?.formattedPriceInMarketReferenceCurrency,
+ marketReferencePriceInUsd,
+ ).toString();
+
+ const maxAmountToSupplyUsd = amountToUsd(
+ maxAmountToSupply,
+ reserve?.formattedPriceInMarketReferenceCurrency,
+ marketReferencePriceInUsd,
+ ).toString();
+
+ // const { disableSupplyButton, disableBorrowButton, alerts } = useReserveActionState({
+ // balance: balance?.amount || '0',
+ // maxAmountToSupply: maxAmountToSupply.toString(),
+ // maxAmountToBorrow: maxAmountToBorrow.toString(),
+ // reserve,
+ // });
+
+ // if (!currentAccount && !isPermissionsLoading) {
+ // return ;
+ // }
+
+ // if (loadingReserves || loadingWalletBalance) {
+ // return ;
+ // }
+
+ const { openSupply, openBorrow } = useModalContext();
+
+ const onSupplyClicked = () => {
+ if (reserve?.isWrappedBaseAsset && selectedAsset === baseAssetSymbol) {
+ openSupply(
+ API_ETH_MOCK_ADDRESS.toLowerCase(),
+ currentMarket,
+ reserve?.name,
+ "reserve",
+ true,
+ );
+ } else {
+ openSupply(
+ reserve.underlyingAsset,
+ currentMarket,
+ reserve?.name,
+ "reserve",
+ true,
+ );
+ }
+ };
+
+ // const { market } = getMarketInfoById(currentMarket);
+
+ return (
+ <>
+
+
+
+
+
+
+
{reserve?.symbol}
+
{reserve?.name}
+
+
+
+
+
+
+
+
+
+
+
Available liquidity
+
+
+
+
+
+
+
Utilization Rate
+
+
+
+
+
+
+
+
+
+
+
+
+ {!currentAccount ? (
+ <>>
+ ) : (
+ <>
+
+ {reserve?.isFrozen || reserve?.isPaused ? (
+
+ {reserve?.isPaused ? (
+ Reserve is Paused
+ ) : (
+ Reserve is Frozen
+ )}
+
+ ) : (
+ <>
+
+ {!isGho && (
+
+ )}
+ {reserve?.borrowingEnabled && (
+ {
+ openBorrow(
+ reserve.underlyingAsset,
+ currentMarket,
+ reserve.name,
+ "reserve",
+ true,
+ );
+ }}
+ />
+ )}
+ {/* {alerts} */}
+
+ >
+ )}
+ >
+ )}
+
+
+
Supply Info
+
+
+
+
+ Total Supplied /
+ $
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Borrow Info
+
+
+
+
+ Total Borrowed /
+ $
+
+
+
+
+
+
+
+
+
+
+ APY, variable /
+ ±%
+
+
+
+
+
+
+
+ APY, stable /
+ %
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/api3-aave-ui/pages/dashboard/index.tsx b/api3-aave-ui/pages/dashboard/index.tsx
new file mode 100644
index 000000000..968afb733
--- /dev/null
+++ b/api3-aave-ui/pages/dashboard/index.tsx
@@ -0,0 +1,212 @@
+import React from "react";
+
+import { useAppDataContext } from "src/hooks/app-data-provider/useAppDataProvider";
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+
+import {
+ normalize,
+ UserIncentiveData,
+ valueToBigNumber,
+} from "@aave/math-utils";
+import { useProtocolDataContext } from "src/hooks/useProtocolDataContext";
+import { ChainId } from "contract-helpers";
+import { useAccount } from "wagmi";
+import { NoData } from "src/components/primitives/NoData";
+import { BorrowAssetsList } from "src/components/dashboard/BorrowAssetsList/BorrowAssetsList";
+import { SupplyAssetsList } from "src/components/dashboard/SupplyAssetsList/SupplyAssetsList";
+import { Box, useMediaQuery, useTheme } from "@mui/material";
+import { HealthFactorNumber } from "src/components/HealthFactorNumber";
+import { useModalContext } from "src/hooks/useModal";
+import { SuppliedPositionsList } from "src/components/dashboard/SuppliedPositionsList /SuppliedPositionsList";
+import { BorrowedPositionsList } from "src/components/dashboard/BorrowedPositionsList/BorrowedPositionsList";
+
+export default function Dashboard() {
+ const { user, reserves, loading } = useAppDataContext();
+ const { currentNetworkConfig, currentMarketData, currentMarket } =
+ useProtocolDataContext();
+ const currentAccount = useAccount();
+
+ const { openClaimRewards } = useModalContext();
+
+ const { claimableRewardsUsd } = Object.keys(
+ user.calculatedUserIncentives,
+ ).reduce(
+ (acc, rewardTokenAddress) => {
+ const incentive: UserIncentiveData =
+ user.calculatedUserIncentives[rewardTokenAddress];
+ const rewardBalance = normalize(
+ incentive.claimableRewards,
+ incentive.rewardTokenDecimals,
+ );
+
+ let tokenPrice = 0;
+ // getting price from reserves for the native rewards for v2 markets
+ if (!currentMarketData.v3 && Number(rewardBalance) > 0) {
+ if (currentMarketData.chainId === ChainId.mainnet) {
+ const aave = reserves.find((reserve) => reserve.symbol === "AAVE");
+ tokenPrice = aave ? Number(aave.priceInUSD) : 0;
+ } else {
+ reserves.forEach((reserve) => {
+ if (
+ reserve.symbol === currentNetworkConfig.wrappedBaseAssetSymbol
+ ) {
+ tokenPrice = Number(reserve.priceInUSD);
+ }
+ });
+ }
+ } else {
+ tokenPrice = Number(incentive.rewardPriceFeed);
+ }
+
+ const rewardBalanceUsd = Number(rewardBalance) * tokenPrice;
+
+ if (rewardBalanceUsd > 0) {
+ if (acc.assets.indexOf(incentive.rewardTokenSymbol) === -1) {
+ acc.assets.push(incentive.rewardTokenSymbol);
+ }
+
+ acc.claimableRewardsUsd += Number(rewardBalanceUsd);
+ }
+
+ return acc;
+ },
+ { claimableRewardsUsd: 0, assets: [] } as {
+ claimableRewardsUsd: number;
+ assets: string[];
+ },
+ );
+
+ const loanToValue =
+ user?.totalCollateralMarketReferenceCurrency === "0"
+ ? "0"
+ : valueToBigNumber(user?.totalBorrowsMarketReferenceCurrency || "0")
+ .dividedBy(user?.totalCollateralMarketReferenceCurrency || "1")
+ .toFixed();
+
+ const theme = useTheme();
+ const downToSM = useMediaQuery(theme.breakpoints.down("sm"));
+ const valueTypographyVariant = downToSM ? "main16" : "main21";
+ const noDataTypographyVariant = downToSM ? "secondary16" : "secondary21";
+
+ return (
+ <>
+
+
+
+
+ My Assets
+
+
+
+
+
Net worth
+
+ {currentAccount ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
Net APY
+
+ {currentAccount && Number(user?.netWorthUSD) > 0 ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
Health factor
+
+ {currentAccount && user?.healthFactor !== "-1" && (
+
+ )}
+
+
+
+
Available rewards
+
+
+ {currentAccount && claimableRewardsUsd > 0 ? (
+
+
+
+
+
+
+
+ ) : (
+
+ )}
+
+
+
+
+ * lending-borrowing market is highly risky, DYOR before investing.
+
+
+
+
+
+ >
+ );
+}
diff --git a/api3-aave-ui/pages/index.tsx b/api3-aave-ui/pages/index.tsx
new file mode 100644
index 000000000..0e4b6ca5e
--- /dev/null
+++ b/api3-aave-ui/pages/index.tsx
@@ -0,0 +1,22 @@
+import type { NextPage } from "next";
+import Head from "next/head";
+import { useEffect } from "react";
+import { useRouter } from "next/router";
+import { populateChainConfigs } from "configuration";
+
+function Home() {
+ const router = useRouter();
+
+ const currentChainConfig = populateChainConfigs();
+ useEffect(() => {
+ if (currentChainConfig.currentMarket === "compound") {
+ router.replace("/markets");
+ } else {
+ router.replace("/dashboard");
+ }
+ }, [currentChainConfig, router]);
+
+ return null;
+}
+
+export default Home;
diff --git a/api3-aave-ui/pages/markets/CompoundDashboard.tsx b/api3-aave-ui/pages/markets/CompoundDashboard.tsx
new file mode 100644
index 000000000..755fcc741
--- /dev/null
+++ b/api3-aave-ui/pages/markets/CompoundDashboard.tsx
@@ -0,0 +1,173 @@
+import { useConnectModal } from "@rainbow-me/rainbowkit";
+import { populateCompoundMarket } from "configuration";
+import React, { useEffect, useMemo } from "react";
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+import SymbolIcon from "src/components/SymbolIcon";
+import { useAppDataContext } from "src/hooks/app-data-provider/useAppDataProvider";
+import { useModalContext } from "src/hooks/useModal";
+import { useProtocolDataContext } from "src/hooks/useProtocolDataContext";
+import { useAccount, useConnect } from "wagmi";
+
+export default function CompoundDashboard() {
+ const { openSupply, openBorrow, openWithdraw } = useModalContext();
+
+ const compoundMarket = populateCompoundMarket();
+ const { currentMarket } = useProtocolDataContext();
+ const { compoundState } = useAppDataContext();
+ const { isConnected } = useAccount();
+ const { openConnectModal } = useConnectModal();
+
+ const onSupplyClicked = () => {
+ const usdc = compoundMarket.marketAsset;
+
+ if (!isConnected) {
+ openConnectModal?.();
+ return;
+ }
+ openSupply(usdc, currentMarket, "USDC", "reserve", true);
+ };
+
+ const onBorrowClicked = () => {
+ if (!isConnected) {
+ openConnectModal?.();
+ return;
+ }
+
+ // withdraw usdc
+ const usdc = compoundMarket.marketAsset;
+ openBorrow(usdc, currentMarket, "USDC", "reserve", true);
+ };
+
+ const isBaseSupplied = useMemo(() => {
+ if (!compoundState?.assetInfo?.baseInfo?.suppliedFormatted) {
+ return false;
+ }
+
+ return compoundState?.assetInfo?.baseInfo?.suppliedFormatted > 0
+ ? true
+ : false;
+ }, [compoundState]);
+
+ const isBorrowCapacityAvailable = useMemo(() => {
+ if (!compoundState?.assetInfo?.baseInfo?.borrowCapacityBase) {
+ return false;
+ }
+
+ return compoundState?.assetInfo?.baseInfo?.borrowCapacityBase > 0
+ ? true
+ : false;
+ }, [compoundState]);
+
+ const isBaseBorrowed = useMemo(() => {
+ if (!compoundState?.assetInfo?.baseInfo?.borrowedInBase) {
+ return false;
+ }
+
+ return compoundState?.assetInfo?.baseInfo?.borrowedInBase > 0
+ ? true
+ : false;
+ }, [compoundState]);
+
+ return (
+
+
+
+
+
+
+
{"USDC Market"}
+
+
+
+
+
+
+
+
+
+
Todal Reserves
+
+ {" "}
+
+
+
+
+
Net Supply APR
+
+ {" "}
+
+
+
+
Net Borrow APR
+
+ {" "}
+
+
+
+
+
Borrow Capacity
+
+
+
+
+
+
+ {isBaseSupplied ? "USDC Supplied" : "USDC Borrowed"}
+
+
+
+
+
+
+
Liquidation Risk
+
+
+
+
+
+
+
+ );
+}
diff --git a/api3-aave-ui/pages/markets/MarketAssetListContainer.tsx b/api3-aave-ui/pages/markets/MarketAssetListContainer.tsx
new file mode 100644
index 000000000..b04c37adb
--- /dev/null
+++ b/api3-aave-ui/pages/markets/MarketAssetListContainer.tsx
@@ -0,0 +1,52 @@
+import React from "react";
+import { useAppDataContext } from "src/hooks/app-data-provider/useAppDataProvider";
+import { useProtocolDataContext } from "src/hooks/useProtocolDataContext";
+import { getGhoReserve } from "src/utils/ghoUtilities";
+import { fetchIconSymbolAndName } from "src/ui-config/reservePatches";
+import { API_ETH_MOCK_ADDRESS } from "contract-helpers";
+import MarketAssetsList from "./MarketAssetsList";
+
+export default function MarketAssetListContainer() {
+ const { reserves, loading } = useAppDataContext();
+ const {
+ currentMarket,
+ currentMarketData,
+ currentNetworkConfig,
+ currentChainId,
+ } = useProtocolDataContext();
+
+ const ghoReserve = getGhoReserve(reserves);
+ const filteredData = reserves
+ // Filter out any non-active reserves
+ .filter((res) => res.isActive)
+ // Filter out all GHO, as we deliberately display it on supported markets
+ .filter((res) => res !== ghoReserve)
+
+ .map((reserve) => ({
+ ...reserve,
+ ...(reserve.isWrappedBaseAsset
+ ? fetchIconSymbolAndName({
+ symbol: currentNetworkConfig.baseAssetSymbol,
+ underlyingAsset: API_ETH_MOCK_ADDRESS.toLowerCase(),
+ })
+ : {}),
+ }));
+ const marketFrozen = !reserves.some((reserve) => !reserve.isFrozen);
+ const showFrozenMarketWarning =
+ marketFrozen &&
+ ["Harmony", "Fantom", "Ethereum AMM"].includes(
+ currentMarketData?.marketTitle,
+ );
+ const unfrozenReserves = filteredData.filter(
+ (r) => !r.isFrozen && !r.isPaused,
+ );
+ const frozenOrPausedReserves = filteredData.filter(
+ (r) => r.isFrozen || r.isPaused,
+ );
+
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/api3-aave-ui/pages/markets/MarketAssetsList.tsx b/api3-aave-ui/pages/markets/MarketAssetsList.tsx
new file mode 100644
index 000000000..e116d3aff
--- /dev/null
+++ b/api3-aave-ui/pages/markets/MarketAssetsList.tsx
@@ -0,0 +1,139 @@
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+import Link from "next/link";
+import React from "react";
+import { ComputedReserveData } from "src/hooks/app-data-provider/useAppDataProvider";
+import { useProtocolDataContext } from "src/hooks/useProtocolDataContext";
+import SymbolIcon from "src/components/SymbolIcon";
+
+type MarketAssetsListProps = {
+ reserves: ComputedReserveData[];
+ loading: boolean;
+};
+
+export default function MarketAssetsList({
+ reserves,
+ loading,
+}: MarketAssetsListProps) {
+ const { currentMarket } = useProtocolDataContext();
+
+ return (
+ <>
+ {/* Market
*/}
+
+ -
+
+
Asset
+
+
+ {" "}
+
+ Total supplied /
+ $
+
+
+
+
+ Supply APY /
+ %
+
+
+
+
+ Total borrowed /
+ $
+
+
+
+ {" "}
+
+ Borrow APY, variable /
+ ±%
+
+
+
+
+ Borrow APY, stable /
+ %
+
+
+
+
+ {reserves?.map((reserve: any) => {
+ return (
+ -
+
+
+
+
+
{reserve?.name}
+
{reserve?.symbol}
+
+
+
+
+
+
+
+
+
+ Details
+
+
+
+ );
+ })}
+
+ >
+ );
+}
diff --git a/api3-aave-ui/pages/markets/compound/MarketAssetListContainerComp.tsx b/api3-aave-ui/pages/markets/compound/MarketAssetListContainerComp.tsx
new file mode 100644
index 000000000..07a5066a0
--- /dev/null
+++ b/api3-aave-ui/pages/markets/compound/MarketAssetListContainerComp.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+import { useAppDataContext } from "src/hooks/app-data-provider/useAppDataProvider";
+
+import MarketAssetsList from "./MarketAssetsListComp";
+
+export default function MarketAssetListContainerComp() {
+ const { loading, compoundState } = useAppDataContext();
+
+ const marketAssets: any = compoundState?.assets;
+
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/api3-aave-ui/pages/markets/compound/MarketAssetsListComp.tsx b/api3-aave-ui/pages/markets/compound/MarketAssetsListComp.tsx
new file mode 100644
index 000000000..f0a85ac10
--- /dev/null
+++ b/api3-aave-ui/pages/markets/compound/MarketAssetsListComp.tsx
@@ -0,0 +1,195 @@
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+import React from "react";
+import { ComputedReserveData } from "src/hooks/app-data-provider/useAppDataProvider";
+import SymbolIcon from "src/components/SymbolIcon";
+import { useProtocolDataContext } from "src/hooks/useProtocolDataContext";
+import { formatUnits } from "viem";
+import { useModalContext } from "src/hooks/useModal";
+import { populateCompoundMarket } from "configuration";
+import { useAccount } from "wagmi";
+import { useConnectModal } from "@rainbow-me/rainbowkit";
+
+type MarketAssetsListProps = {
+ reserves: ComputedReserveData[];
+ loading: boolean;
+};
+
+function MarketItem({ reserve }: any) {
+ const { openSupply, openBorrow } = useModalContext();
+ const { currentMarket, currentNetworkConfig } = useProtocolDataContext();
+ const compoundMarket = populateCompoundMarket();
+ const { isConnected } = useAccount();
+ const { openConnectModal } = useConnectModal();
+
+ const onSupplyClicked = () => {
+ if (!isConnected) {
+ openConnectModal?.();
+ return;
+ }
+
+ openSupply(
+ reserve?.asset?.address,
+ currentMarket,
+ reserve?.asset?.name,
+ "reserve",
+ true,
+ );
+ };
+
+ const onBorrowClicked = () => {
+ if (!isConnected) {
+ openConnectModal?.();
+ return;
+ }
+
+ openBorrow(
+ reserve?.asset?.address,
+ currentMarket,
+ reserve?.asset?.name,
+ "reserve",
+ true,
+ );
+ };
+
+ return (
+
+
+
+
+
+
{reserve?.asset?.name}
+
{reserve?.asset?.symbol}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default function MarketAssetsListComp({
+ reserves,
+ loading,
+}: MarketAssetsListProps) {
+ return (
+ <>
+ {/* Market
*/}
+
+ -
+
+
Collateral Asset
+
+
+ {" "}
+
+ Oracle Price /
+ $
+
+
+
+
+ Collateral Factor /
+ %
+
+
+
+
+ Liquidation Factor /
+ %
+
+
+
+
+ Liquidation Panality /
+ %
+
+
+
+
+
+ Collateral Supplied /
+
+
+
+
+
+
+ Action
+ {""}
+
+
+
+
+ {reserves?.map((reserve: any, index: number) => {
+ return ;
+ })}
+
+ >
+ );
+}
diff --git a/api3-aave-ui/pages/markets/index.tsx b/api3-aave-ui/pages/markets/index.tsx
new file mode 100644
index 000000000..b4c69efa9
--- /dev/null
+++ b/api3-aave-ui/pages/markets/index.tsx
@@ -0,0 +1,97 @@
+"use client";
+import React from "react";
+import { useMediaQuery, useTheme } from "@mui/material";
+
+import { useAppDataContext } from "src/hooks/app-data-provider/useAppDataProvider";
+import { valueToBigNumber } from "@aave/math-utils";
+import { FormattedNumber } from "src/components/primitives/FormattedNumber";
+import MarketAssetListContainer from "./MarketAssetListContainer";
+import { populateChainConfigs } from "configuration";
+import MarketAssetListContainerComp from "./compound/MarketAssetListContainerComp";
+
+import CompoundDashboard from "./CompoundDashboard";
+
+export default function Markets() {
+ const { reserves, loading } = useAppDataContext();
+
+ const aggregatedStats = reserves.reduce(
+ (acc, reserve) => {
+ return {
+ totalLiquidity: acc.totalLiquidity.plus(reserve.totalLiquidityUSD),
+ totalDebt: acc.totalDebt.plus(reserve.totalDebtUSD),
+ };
+ },
+ {
+ totalLiquidity: valueToBigNumber(0),
+ totalDebt: valueToBigNumber(0),
+ },
+ );
+
+ const theme = useTheme();
+ const downToSM = useMediaQuery(theme.breakpoints.down("sm"));
+ const valueTypographyVariant = downToSM ? "main16" : "main21";
+ const symbolsVariant = downToSM ? "secondary16" : "secondary21";
+
+ const currenChainConfig = populateChainConfigs();
+
+ return (
+ <>
+ {currenChainConfig.currentMarket === "compound" ? (
+
+ ) : (
+
+
+
+ Markets
+
+
+
+
Total market size
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+ {currenChainConfig.currentMarket === "compound" ? (
+
+ ) : (
+
+ )}
+
+
+ >
+ );
+}
diff --git a/api3-aave-ui/pages/stake/index.tsx b/api3-aave-ui/pages/stake/index.tsx
new file mode 100644
index 000000000..90ed4904e
--- /dev/null
+++ b/api3-aave-ui/pages/stake/index.tsx
@@ -0,0 +1,77 @@
+import { useWeb3Context } from "src/hooks/lib/hooks/useWeb3Context";
+import StakeCard from "../../components/stake/StakeCard";
+import StakeHeader from "../../components/stake/StakeHeader";
+import { useUserStakeUiData } from "src/hooks/stake/useUserStakeUiData";
+import { useGeneralStakeUiData } from "src/hooks/stake/useGeneralStakeUiData";
+import { useModalContext } from "src/hooks/useModal";
+import { formatEther, formatUnits } from "ethers/lib/utils";
+import { BigNumber } from "ethers";
+
+export default function Stake() {
+ const { currentAccount, loading, chainId } = useWeb3Context();
+
+ const { data: stakeUserResult, isLoading: stakeUserResultLoading } =
+ useUserStakeUiData();
+ const { data: stakeGeneralResult, isLoading: stakeGeneralResultLoading } =
+ useGeneralStakeUiData();
+
+ const stakeDataLoading = stakeUserResultLoading || stakeGeneralResultLoading;
+
+ const {
+ openStake,
+ openStakeCooldown,
+ openUnstake,
+ openStakeRewardsClaim,
+ openStakeRewardsRestakeClaim,
+ } = useModalContext();
+
+ // Total funds at Safety Module (stkaave tvl + stkbpt tvl)
+ const tvl = formatUnits(
+ BigNumber.from(stakeGeneralResult?.aave.stakeTokenTotalSupply || "0")
+ .mul(stakeGeneralResult?.aave.stakeTokenPriceEth || "0")
+ .add(
+ BigNumber.from(
+ stakeGeneralResult?.bpt.stakeTokenTotalSupply || "0",
+ ).mul(stakeGeneralResult?.bpt.stakeTokenPriceEth || "0"),
+ )
+ .mul(stakeGeneralResult?.ethPriceUsd || 1),
+ 18 + 18 + 8, // 2x total supply (18 decimals), 1x ethPriceUSD (8 decimals)
+ );
+
+ // Total AAVE Emissions (stkaave dps + stkbpt dps)
+ const stkEmission = formatEther(
+ BigNumber.from(stakeGeneralResult?.aave.distributionPerSecond || "0")
+ .add(stakeGeneralResult?.bpt.distributionPerSecond || "0")
+ .mul("86400"),
+ );
+
+ return (
+
+
+
+ openStake("aave", "PZM")} // assetName, icon
+ onCooldownAction={() => openStakeCooldown("aave")}
+ onUnstakeAction={() => openUnstake("aave", "PZM")}
+ onStakeRewardClaimAction={() => openStakeRewardsClaim("aave", "PZM")}
+ onStakeRewardClaimRestakeAction={() =>
+ openStakeRewardsRestakeClaim("aave", "PZM")
+ }
+ // headerAction={}
+ hasDiscountProgram={false}
+ />
+
+
+ );
+}
diff --git a/api3-aave-ui/postcss.config.js b/api3-aave-ui/postcss.config.js
new file mode 100644
index 000000000..33ad091d2
--- /dev/null
+++ b/api3-aave-ui/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/api3-aave-ui/prettier.config.js b/api3-aave-ui/prettier.config.js
new file mode 100644
index 000000000..fd9374686
--- /dev/null
+++ b/api3-aave-ui/prettier.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ plugins: ['prettier-plugin-tailwindcss'],
+ }
diff --git a/api3-aave-ui/public/images/favicon.png b/api3-aave-ui/public/images/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..0daebab93416470afd4b79bafeb00d15f9daf8f7
GIT binary patch
literal 92196
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