├── .eslintrc.json
├── .github
└── workflows
│ └── issue-to-project.yml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── apollo
├── client.ts
└── generated
│ ├── fragmentMetadata.json
│ ├── graphql-codegen-generated.ts
│ ├── operations.ts
│ └── schema.graphql
├── assets
├── icons
│ ├── CoingeckoIcon.tsx
│ ├── beetx-smarts.svg
│ ├── beetx-thinking.svg
│ ├── chevron_down3.svg
│ ├── discord.svg
│ ├── github.svg
│ ├── medium.svg
│ ├── points.svg
│ ├── pool-icon-1.svg
│ ├── pool-icon-2.svg
│ ├── pool-icon-3.svg
│ ├── scales.svg
│ └── twitter.svg
├── images
│ ├── beets-token-info-OP.png
│ ├── beets-token-info.png
│ ├── coingecko.svg
│ ├── degen-band.png
│ ├── fantom-logo.png
│ ├── footer-OP.png
│ ├── invest-masthead-image-OP.png
│ ├── invest-masthead-image.png
│ ├── optimism.svg
│ ├── pool-owner.png
│ ├── powered-by-balancer.svg
│ ├── reliquary
│ │ ├── 1.png
│ │ ├── 10.png
│ │ ├── 11.png
│ │ ├── 1x1-transparent.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ ├── 5.png
│ │ ├── 6.png
│ │ ├── 7.png
│ │ ├── 8.png
│ │ ├── 9.png
│ │ ├── approve-beets.png
│ │ ├── approve-deposit.png
│ │ ├── approve-relayer.png
│ │ ├── approve-relic.png
│ │ ├── approve-vault.png
│ │ ├── approve-wftm.png
│ │ ├── background.png
│ │ ├── complete.png
│ │ ├── create-relic.png
│ │ ├── finished-relic.png
│ │ ├── migrate-legacy.png
│ │ ├── migrate-process.png
│ │ ├── migrated-minted-fbeets.png
│ │ └── unstake-fbeets.png
│ ├── rq-1.png
│ ├── rq-2.png
│ ├── rq-3.png
│ ├── sFTMx-header.png
│ ├── swap-masthead-image-OP.png
│ ├── swap-masthead-image.png
│ ├── why-us-OP.png
│ └── why-us.png
└── logo
│ ├── BeetsBalLogo.tsx
│ ├── BeetsLogo.tsx
│ ├── aura_iso_colors.png
│ ├── beets-bal-2.svg
│ ├── beets-bal-powered.svg
│ ├── beets-bal.svg
│ ├── beets-logo.svg
│ ├── fmoney-pfp.png
│ ├── gyro-white.png
│ └── merkl2x.png
├── codegen.yml
├── components
├── accordion
│ └── BeetsAccordion.tsx
├── animated-progress
│ └── AnimatedProgress.tsx
├── animation
│ ├── FadeInBox.tsx
│ ├── FadeInOutBox.tsx
│ ├── chakra.tsx
│ └── chevron
│ │ └── AnimatedChevrons.tsx
├── apr-tooltip
│ ├── AprText.tsx
│ ├── AprTooltip.tsx
│ └── StarsIcon.tsx
├── avatar
│ └── WalletUserAvatar.tsx
├── badge
│ └── PercentChangeBadge.tsx
├── box
│ ├── BeetsBox.tsx
│ ├── BeetsBoxHeader.tsx
│ └── BeetsBoxLineItem.tsx
├── bridge
│ ├── BeetsBridgeModal.tsx
│ └── useBeetsBalance.tsx
├── button
│ ├── BeetsBatchRelayerApprovalButton.tsx
│ ├── BeetsMinterApprovalButton.tsx
│ ├── BeetsSubmitTransactionButton.tsx
│ ├── BeetsTokenApprovalButton.tsx
│ ├── BeetsTransactionStepsSubmit.tsx
│ └── WalletConnectButton.tsx
├── card
│ ├── Card.tsx
│ └── CardRow.tsx
├── carousel
│ └── BeetsCarousel.tsx
├── charts
│ └── TokenPriceLineChart.tsx
├── fallback
│ └── FallbackPlaceholder.tsx
├── fonts
│ └── BeetsFonts.tsx
├── icons
│ ├── IconDiscord.tsx
│ ├── IconGithub.tsx
│ ├── IconGlobe.tsx
│ ├── IconMedium.tsx
│ ├── IconTelegram.tsx
│ ├── IconTwitter.tsx
│ └── IconWallet.tsx
├── info-button
│ └── InfoButton.tsx
├── inputs
│ ├── BeetsInput.tsx
│ ├── BeetsTokenInputWithSlider.tsx
│ ├── FtmTokenInput.tsx
│ ├── PresetSelector.tsx
│ └── TokenInput.tsx
├── link
│ └── NextLink.tsx
├── masthead
│ └── PageMasthead.tsx
├── modal
│ ├── BeetsModal.tsx
│ └── ModalSectionHeadline.tsx
├── multi-select
│ └── MultiSelect.tsx
├── pool-badge
│ ├── PoolBadgeSmall.tsx
│ ├── assets
│ │ ├── badge-experimental.gif
│ │ ├── boosted-by-beefy-exactly.png
│ │ ├── built-by-gyroscope.png
│ │ ├── gyro-short.svg
│ │ ├── overnight-boosted-small.png
│ │ ├── reaper-aave-boosted-small.png
│ │ ├── reaper-aave-granary-boosted-small.png
│ │ ├── reaper-boosted.png
│ │ └── reaper-sonne-boosted.png
│ └── lib
│ │ └── pool-badge-tooltips.ts
├── popup-menu
│ └── TextButtonPopupMenu.tsx
├── progress-bar
│ └── TopProgressBar.tsx
├── providers
│ └── Compose.tsx
├── slippage
│ └── SlippageTextLinkMenu.tsx
├── steps
│ └── HorizontalSteps.tsx
├── switch-button
│ └── SwitchButton.tsx
├── table
│ └── PaginatedTable.tsx
├── tabs
│ └── BeetsTab.tsx
├── toast
│ ├── BeetsToast.tsx
│ ├── TransactionStatusToast.tsx
│ └── toast-util.ts
├── token-select-inline
│ └── TokenSelectInline.tsx
├── token-select
│ ├── GenericTokenSelectModal.tsx
│ ├── TokenActionRow.tsx
│ ├── TokenImportAlertDialog.tsx
│ ├── TokenRow.tsx
│ ├── TokenSelectSearchInput.tsx
│ └── TokenSelectTokenList.tsx
├── token
│ ├── PoolTokenPill.tsx
│ ├── TokenAmountPill.tsx
│ ├── TokenAvatar.tsx
│ ├── TokenAvatarSet.tsx
│ ├── TokenAvatarSetInList.tsx
│ └── TokenRow.tsx
├── tooltip
│ ├── BeetsTooltip.tsx
│ └── CustomTooltip.tsx
├── transaction
│ ├── SubTransactionSubmittedContent.tsx
│ └── TransactionSubmittedContent.tsx
├── typography
│ ├── BeetsHeadline.tsx
│ └── BeetsSubHeadline.tsx
└── user-warning
│ └── UserWarning.tsx
├── declarations.d.ts
├── lib
├── abi
│ ├── AaveWrapping.json
│ ├── BalancerPoolToken.json
│ ├── BalancerPseudoMinter.json
│ ├── BalancerQueries.json
│ ├── BalancerRelayer.json
│ ├── BalancerSorQueries.json
│ ├── BasePoolFactory.json
│ ├── BatchRelayer.json
│ ├── BatchRelayerLibrary.json
│ ├── BatchRelayerView.json
│ ├── BeethovenCheckpointer.json
│ ├── BeethovenxMasterChef.json
│ ├── BeethovenxNft.json
│ ├── BeetsOftProxyV2.json
│ ├── BooMirrorWorldStaking.json
│ ├── ChildChainGaugeRewardHelper.json
│ ├── ConvergentCurvePool.json
│ ├── DelegateRegistry.json
│ ├── ERC20.json
│ ├── Erc4626Wrapping.json
│ ├── ExchangeProxy.json
│ ├── FBeetsBarStaking.json
│ ├── FTMStaking.json
│ ├── FreshBeets.json
│ ├── GaugeActions.json
│ ├── GaugeWorkingBalanceHelper.json
│ ├── LinearPool.json
│ ├── LinearPoolRebalancer.json
│ ├── LiquidityGaugeV5.json
│ ├── LiquidityGaugeV6.json
│ ├── MasterChefStaking.json
│ ├── MultiBeetsMigration.json
│ ├── ReaperManualRebalancer.json
│ ├── ReaperWrapping.json
│ ├── Reliquary.json
│ ├── ReliquaryStaking.json
│ ├── StablePhantomPool.json
│ ├── StablePool.json
│ ├── StaticATokenRateProvider.json
│ ├── TarotWrapping.json
│ ├── TimeBasedRewarder.json
│ ├── Vault.json
│ ├── VaultAbi.json
│ ├── VaultActions.json
│ ├── WETH.json
│ ├── WeightedPool.json
│ ├── WeightedPool2Tokens.json
│ ├── WeightedPool2TokensFactory.json
│ ├── WeightedPoolFactory.json
│ ├── WeightedPoolFactoryV4.json
│ └── YearnWrapping.json
├── config
│ ├── fantom.ts
│ ├── network-config-type.ts
│ ├── network-config.ts
│ └── optimism.ts
├── global
│ ├── batchJsonRpcProvider.ts
│ ├── constants.ts
│ ├── graphql
│ │ └── global.gql
│ ├── network.ts
│ ├── useEarlyLudwigNft.ts
│ ├── useGlobalWarnings.tsx
│ ├── useMasterChefHarvestAllRewards.ts
│ ├── useNetworkConfig.ts
│ ├── useOldBeetsBalance.ts
│ ├── useSlippage.ts
│ ├── useStakingBoosts.ts
│ ├── useStakingClaimRewards.ts
│ ├── useStakingDeposit.ts
│ ├── useStakingMintableRewards.ts
│ ├── useStakingPendingRewards.ts
│ ├── useStakingTotalStakedBalance.ts
│ ├── useStakingWithdraw.ts
│ ├── useSubgraphQuery.ts
│ └── useToken.tsx
├── services
│ ├── batch-relayer
│ │ ├── batch-relayer.service.ts
│ │ ├── extensions
│ │ │ ├── aave-wrapping.service.ts
│ │ │ ├── boo-mirror-world-staking.service.ts
│ │ │ ├── erc4626-wrapping.service.ts
│ │ │ ├── fbeets-bar-staking.service.ts
│ │ │ ├── gauge-actions.service.ts
│ │ │ ├── masterchef-staking.service.ts
│ │ │ ├── reaper-wrapping.service.ts
│ │ │ ├── reliquary-staking.service.ts
│ │ │ ├── tarot-supply-vault.service.ts
│ │ │ ├── vault-actions.service.ts
│ │ │ └── yearn-wrapping.service.ts
│ │ └── relayer-types.ts
│ ├── nft
│ │ └── nft.service.ts
│ ├── pool
│ │ ├── lib
│ │ │ ├── big-int-basic-operations.ts
│ │ │ ├── old-big-number.ts
│ │ │ ├── pool-base.service.ts
│ │ │ ├── pool-composable-exit.service.ts
│ │ │ ├── pool-composable-join.service.ts
│ │ │ ├── pool-proportional-invest.service.ts
│ │ │ ├── stable-math.ts
│ │ │ └── util.ts
│ │ ├── pool-composable-stable.service.ts
│ │ ├── pool-gyro.service.ts
│ │ ├── pool-meta-stable.service.ts
│ │ ├── pool-on-chain-balance.service.ts
│ │ ├── pool-phantom-stable-util.ts
│ │ ├── pool-phantom-stable.service.ts
│ │ ├── pool-stable.service.ts
│ │ ├── pool-types.ts
│ │ ├── pool-util.ts
│ │ ├── pool-weighted-boosted.service.ts
│ │ ├── pool-weighted-compose.service.ts
│ │ ├── pool-weighted-v2.service.ts
│ │ ├── pool-weighted.service.ts
│ │ └── sor-query.service.ts
│ ├── rpc-provider
│ │ └── static-json-rpc-batch-provier.ts
│ ├── staking
│ │ ├── fresh-beets.service.ts
│ │ ├── gauge-staking.service.ts
│ │ ├── gauge.service.ts
│ │ ├── master-chef.service.ts
│ │ ├── reliquary-zap.service.ts
│ │ ├── reliquary.service.ts
│ │ ├── sftmx.service.ts
│ │ └── staking-types.ts
│ ├── token
│ │ ├── concerns
│ │ │ ├── allowances.concern.ts
│ │ │ ├── balances.concern.ts
│ │ │ └── metadata.concern.ts
│ │ ├── token-types.ts
│ │ ├── token-util.ts
│ │ └── token.service.ts
│ └── util
│ │ ├── gas-price.service.ts
│ │ ├── multicaller.service.ts
│ │ └── snapshot.service.ts
├── user
│ ├── graphql
│ │ └── user.gql
│ ├── useUserAccount.ts
│ ├── useUserBalances.tsx
│ ├── useUserData.tsx
│ ├── useUserImportedTokens.ts
│ ├── useUserPendingRewards.ts
│ └── useUserTokenBalances.tsx
├── util
│ ├── address.ts
│ ├── apr-util.ts
│ ├── custom-hooks.ts
│ ├── ethers-v6.ts
│ ├── etherscan.ts
│ ├── input-util.ts
│ ├── number-formats.ts
│ ├── random.ts
│ ├── transaction-util.ts
│ ├── urls.ts
│ ├── useAllowances.ts
│ ├── useApproveBatchRelayer.ts
│ ├── useApproveMinter.ts
│ ├── useApproveToken.ts
│ ├── useBalances.ts
│ ├── useHasBatchRelayerApproval.ts
│ ├── useHasMinterApproval.ts
│ ├── useMultiCall.ts
│ ├── useSubmitTransaction.tsx
│ ├── useUnwrapEth.ts
│ ├── useUserAllowances.ts
│ ├── useWrapEth.ts
│ └── web3.ts
└── wallet
│ └── useWalletConnectMetadata.tsx
├── modules
├── compose
│ ├── AdvancedPoolComposeFeeManager.tsx
│ ├── AdvancedPoolComposeFees.tsx
│ ├── AdvancedPoolComposeName.tsx
│ ├── AdvancedPoolComposeProgress.tsx
│ ├── AdvancedPoolComposeSubmit.tsx
│ ├── AdvancedPoolComposeTokens.tsx
│ ├── AdvancedPoolCreation.tsx
│ ├── ComposeChooseFlowType.tsx
│ ├── ComposeFlow.tsx
│ ├── ComposeProvider.tsx
│ ├── FinalisePoolComposeActions.tsx
│ ├── PoolComposePreview.tsx
│ ├── PreviewPoolTokenFees.tsx
│ ├── PreviewPoolTokenSelections.tsx
│ ├── SimpleCreationChooseTokens.tsx.tsx
│ └── lib
│ │ ├── useGetComposePoolId.ts
│ │ └── usePoolCreate.ts
├── global
│ └── GlobalRenderer.tsx
├── migrate
│ ├── BeetsMigration.tsx
│ ├── BeetsMigrationButton.tsx
│ └── lib
│ │ └── useMigrateBeets.ts
├── nav
│ ├── Footer.tsx
│ ├── FooterLink.tsx
│ ├── Navbar.tsx
│ ├── NavbarAdditionalLinksMenu.tsx
│ ├── NavbarLink.tsx
│ ├── NavbarMobile.tsx
│ ├── NavbarPendingRewards.tsx
│ ├── NavbarPendingRewardsReliquary.tsx
│ ├── NavbarWalletConnectButton.tsx
│ ├── NetworkSelectorPopover.tsx
│ ├── SubNavBar.tsx
│ ├── SubNavBarStat.tsx
│ └── lib
│ │ ├── useGaugeClaimGetContractCallData.ts
│ │ ├── useUserGaugeClaimAllPendingRewards.ts
│ │ └── useUserHarvestAllPendingRewards.ts
├── pool
│ ├── detail
│ │ ├── Pool.tsx
│ │ └── components
│ │ │ ├── PoolDetailActions.tsx
│ │ │ ├── PoolDetailCharts.tsx
│ │ │ ├── PoolDetailMyBalance.tsx
│ │ │ ├── PoolDetailPossibleYieldText.tsx
│ │ │ ├── PoolHeader.tsx
│ │ │ ├── PoolHeaderStaking.tsx
│ │ │ ├── PoolHeaderStats.tsx
│ │ │ ├── charts
│ │ │ ├── PoolDetailBptPriceChart.tsx
│ │ │ ├── PoolDetailFeesChart.tsx
│ │ │ ├── PoolDetailVolumeLiquidityChart.tsx
│ │ │ └── chart-util.ts
│ │ │ ├── composition
│ │ │ ├── PoolComposition.tsx
│ │ │ ├── PoolCompositionRow.tsx
│ │ │ └── PoolCompositionToken.tsx
│ │ │ ├── stats
│ │ │ ├── PoolOverallStats.tsx
│ │ │ ├── PoolStats.tsx
│ │ │ ├── PoolUserStakedStats.tsx
│ │ │ └── PoolUserStats.tsx
│ │ │ ├── thirdparty
│ │ │ ├── PoolHeaderPoints.tsx
│ │ │ ├── PoolHeaderStakingAura.tsx
│ │ │ ├── PoolHeaderStakingFmoney.tsx
│ │ │ ├── PoolHeaderStakingMerkl.tsx
│ │ │ └── PoolStatsGyroscope.tsx
│ │ │ └── warning
│ │ │ ├── PoolDetailWarning.tsx
│ │ │ ├── PoolMigrateLegacyFbeetsWarning.tsx
│ │ │ ├── PoolOvernightWarning.tsx
│ │ │ ├── PoolStakeInFarmWarning.tsx
│ │ │ └── PoolWarnings.tsx
│ ├── invest
│ │ ├── PoolInvestModal.tsx
│ │ ├── components
│ │ │ ├── PoolInvestActions.tsx
│ │ │ ├── PoolInvestCustom.tsx
│ │ │ ├── PoolInvestPreview.tsx
│ │ │ ├── PoolInvestPriceImpact.tsx
│ │ │ ├── PoolInvestProportional.tsx
│ │ │ ├── PoolInvestSettings.tsx
│ │ │ ├── PoolInvestStablePoolDescription.tsx
│ │ │ ├── PoolInvestSummary.tsx
│ │ │ ├── PoolInvestTypeChoice.tsx
│ │ │ └── PoolInvestWeightedPoolDescription.tsx
│ │ └── lib
│ │ │ ├── useInitJoinPool.ts
│ │ │ ├── useInvest.ts
│ │ │ ├── useInvestState.ts
│ │ │ ├── useJoinPool.ts
│ │ │ ├── usePoolGetMaxProportionalInvestmentAmount.ts
│ │ │ ├── usePoolInitJoinContractCallData.ts
│ │ │ ├── usePoolJoinGetBptOutAndPriceImpactForTokensIn.ts
│ │ │ ├── usePoolJoinGetContractCallData.ts
│ │ │ └── usePoolJoinGetProportionalInvestmentAmount.ts
│ ├── lib
│ │ ├── usePool.tsx
│ │ ├── usePoolComposableUserPoolTokenBalances.tsx
│ │ ├── usePoolGaugeClaimRewardsGetContractCallData.ts
│ │ ├── usePoolUserBptBalance.tsx
│ │ ├── usePoolUserDepositBalance.tsx
│ │ ├── usePoolUserInvestedTokenBalances.tsx
│ │ ├── usePoolUserPendingRewards.tsx
│ │ ├── usePoolUserTokenBalancesInWallet.tsx
│ │ └── usePoolWithOnChainData.tsx
│ ├── pool.gql
│ ├── stake
│ │ ├── PoolMigrateGaugeModal.tsx
│ │ ├── PoolStakeModal.tsx
│ │ ├── PoolUnstakeModal.tsx
│ │ └── lib
│ │ │ ├── useCheckpointTrigger.ts
│ │ │ ├── useGaugeCheckpoint.ts
│ │ │ ├── useGaugeStakingMigration.ts
│ │ │ ├── useGaugeUnstakeGetContractCallData.ts
│ │ │ ├── usePoolUserStakingAllowance.ts
│ │ │ └── useVeMigrationTrigger.ts
│ └── withdraw
│ │ ├── PoolWithdrawModal.tsx
│ │ ├── components
│ │ ├── PoolWithdrawPreview.tsx
│ │ ├── PoolWithdrawProportional.tsx
│ │ ├── PoolWithdrawSettings.tsx
│ │ ├── PoolWithdrawSingleAsset.tsx
│ │ ├── PoolWithdrawStablePoolDescription.tsx
│ │ ├── PoolWithdrawSummary.tsx
│ │ ├── PoolWithdrawTypeChoice.tsx
│ │ └── PoolWithdrawWeightedPoolDescription.tsx
│ │ └── lib
│ │ ├── useExitPool.ts
│ │ ├── usePoolExitGetBptInForSingleAssetWithdraw.ts
│ │ ├── usePoolExitGetContractCallData.ts
│ │ ├── usePoolExitGetProportionalWithdrawEstimate.ts
│ │ ├── usePoolExitGetSingleAssetWithdrawForBptIn.ts
│ │ ├── useWithdraw.ts
│ │ └── useWithdrawState.ts
├── pools
│ ├── PoolList.tsx
│ ├── components
│ │ ├── PoolListAttributeMultiSelect.tsx
│ │ ├── PoolListItem.tsx
│ │ ├── PoolListItemStaking.tsx
│ │ ├── PoolListItemWarning.tsx
│ │ ├── PoolListMobileHeader.tsx
│ │ ├── PoolListSearch.tsx
│ │ ├── PoolListSortLink.tsx
│ │ ├── PoolListTableHeader.tsx
│ │ ├── PoolListTabs.tsx
│ │ ├── PoolListTokenMultiSelect.tsx
│ │ ├── PoolListTop.tsx
│ │ └── thirdparty
│ │ │ ├── PoolListItemPoints.tsx
│ │ │ ├── PoolListItemStakingAura.tsx
│ │ │ ├── PoolListItemStakingFmoney.tsx
│ │ │ └── PoolListItemStakingMerkl.tsx
│ ├── pools.gql
│ └── usePoolList.tsx
├── recovery-exit
│ ├── RecoveryExitContent.tsx
│ ├── components
│ │ ├── RecoveryExitWithdrawListItem.tsx
│ │ └── RecoveryExitWithdrawTableHeader.tsx
│ └── lib
│ │ ├── useDoRecoveryExit.ts
│ │ └── useGetRecoveryPoolTokens.ts
├── reliquary
│ ├── ReliquaryLanding.tsx
│ ├── components
│ │ ├── DelegateClearButton.tsx
│ │ ├── DelegateSetButton.tsx
│ │ ├── RelicBurnButton.tsx
│ │ ├── RelicCarousel.tsx
│ │ ├── RelicLevelUpButton.tsx
│ │ ├── RelicMaturityModal.tsx
│ │ ├── RelicSlide.tsx
│ │ ├── RelicSlideApr.tsx
│ │ ├── RelicSlideInfo.tsx
│ │ ├── RelicSlideMainInfo.tsx
│ │ ├── ReliquaryBatchRelayerApprovalButton.tsx
│ │ ├── ReliquaryConnectWallet.tsx
│ │ ├── ReliquaryMigrateModal.tsx
│ │ ├── ReliquaryTokensBreakdown.tsx
│ │ ├── ReliquaryTransactionStepsSubmit.tsx
│ │ ├── charts
│ │ │ ├── RelicMaturity.tsx
│ │ │ ├── RelicMaturityBarChart.tsx
│ │ │ ├── ReliquaryCurveChart.tsx
│ │ │ ├── ReliquaryDetailsCharts.tsx
│ │ │ ├── ReliquaryLiquidityChart.tsx
│ │ │ ├── ReliquaryMaBEETSLevelChart.tsx
│ │ │ ├── ReliquaryMaturityChart.tsx
│ │ │ └── ReliquaryRelicsCountChart.tsx
│ │ ├── stats
│ │ │ ├── ReliquaryGlobalStats.tsx
│ │ │ └── ReliquaryOverallStats.tsx
│ │ └── unused
│ │ │ ├── Relic.tsx
│ │ │ ├── RelicAchievements.tsx
│ │ │ ├── RelicApr.tsx
│ │ │ ├── RelicHeader.tsx
│ │ │ ├── RelicLiquidity.tsx
│ │ │ ├── RelicNFT.tsx
│ │ │ ├── RelicRewards.tsx
│ │ │ ├── RelicStats.tsx
│ │ │ ├── Reliquary.tsx
│ │ │ ├── ReliquaryCard.tsx
│ │ │ ├── ReliquaryInvest.tsx
│ │ │ ├── ReliquaryMigrateDemoButton.tsx
│ │ │ ├── ReliquaryMyStats.tsx
│ │ │ └── ReliquaryWithdrawDemoButton.tsx
│ ├── detail
│ │ └── ReliquaryPool.tsx
│ ├── invest
│ │ ├── ReliquaryInvestModal.tsx
│ │ ├── components
│ │ │ ├── ReliquaryInvestActions.tsx
│ │ │ ├── ReliquaryInvestCustom.tsx
│ │ │ ├── ReliquaryInvestDepositImpact.tsx
│ │ │ ├── ReliquaryInvestImage.tsx
│ │ │ ├── ReliquaryInvestPreview.tsx
│ │ │ ├── ReliquaryInvestProportional.tsx
│ │ │ ├── ReliquaryInvestSettings.tsx
│ │ │ ├── ReliquaryInvestSummary.tsx
│ │ │ ├── ReliquaryInvestTitle.tsx
│ │ │ └── ReliquaryInvestTypeChoice.tsx
│ │ └── lib
│ │ │ ├── useReliquaryInvest.ts
│ │ │ ├── useReliquaryInvestState.ts
│ │ │ ├── useReliquaryJoinGetBptOutAndPriceImpactForTokensIn.ts
│ │ │ └── useReliquaryJoinGetProportionalInvestmentAmount.ts
│ ├── lib
│ │ ├── reliquary-helpers.ts
│ │ ├── useAllRelicsDepositBalances.tsx
│ │ ├── useAllRelicsWithdrawAndHarvestContractCallData.tsx
│ │ ├── useBatchRelayerHasApprovedForAll.ts
│ │ ├── useBatchRelayerHasRelicApproval.ts
│ │ ├── useBatchRelayerRelicApprove.ts
│ │ ├── useBridgeBeets.ts
│ │ ├── useDelegateClear.tsx
│ │ ├── useDelegateSet.tsx
│ │ ├── useDelegation.tsx
│ │ ├── useLegacyFbeetsBalance.ts
│ │ ├── useRelicBurn.tsx
│ │ ├── useRelicDepositBalance.tsx
│ │ ├── useRelicHarvestRewards.ts
│ │ ├── useRelicPendingRewards.ts
│ │ ├── useReliquary.ts
│ │ ├── useReliquaryCurrentStep.tsx
│ │ ├── useReliquaryDepositContractCallData.ts
│ │ ├── useReliquaryDepositImpact.ts
│ │ ├── useReliquaryFbeetsMigrateContractCallData.ts
│ │ ├── useReliquaryGlobalStats.ts
│ │ ├── useReliquaryHarvestAllContractCallData.ts
│ │ ├── useReliquaryHarvestAllRewards.ts
│ │ ├── useReliquaryLevelUp.ts
│ │ ├── useReliquaryPendingRewards.ts
│ │ ├── useReliquaryWithdrawAndHarvestContractCallData.ts
│ │ └── useReliquaryZap.ts
│ ├── migrate
│ │ ├── ReliquarySonicMigrateModal.tsx
│ │ └── components
│ │ │ ├── ReliquarySonicMigrateBridgeBeets.tsx
│ │ │ ├── ReliquarySonicMigrateBridgeFtm.tsx
│ │ │ ├── ReliquarySonicMigrateExitRelics.tsx
│ │ │ ├── ReliquarySonicMigrateNextSteps.tsx
│ │ │ ├── ReliquarySonicMigrateStakeS.tsx
│ │ │ └── ReliquarySonicMigrateUnwrapFtm.tsx
│ ├── reliquary.gql
│ └── withdraw
│ │ ├── ReliquaryWithdrawModal.tsx
│ │ ├── components
│ │ ├── ReliquaryWithdrawDescription.tsx
│ │ ├── ReliquaryWithdrawPreview.tsx
│ │ ├── ReliquaryWithdrawProportional.tsx
│ │ ├── ReliquaryWithdrawSettings.tsx
│ │ ├── ReliquaryWithdrawSingleAsset.tsx
│ │ ├── ReliquaryWithdrawSummary.tsx
│ │ └── ReliquaryWithdrawTypeChoice.tsx
│ │ └── lib
│ │ ├── useReliquaryExitGetBptInForSingleAssetWithdraw.ts
│ │ ├── useReliquaryExitGetProportionalWithdrawEstimate.ts
│ │ ├── useReliquaryExitGetSingleAssetWithdrawForBptIn.ts
│ │ ├── useReliquaryWithdraw.ts
│ │ └── useReliquaryWithdrawState.ts
└── sftmx
│ ├── SftmxLanding.tsx
│ ├── components
│ ├── charts
│ │ ├── SftmxChartsFtmStakedFree.tsx
│ │ └── SftmxChartsFtmValidator.tsx
│ ├── stats
│ │ ├── SftmxOverallStats.tsx
│ │ ├── SftmxStatsFtmStakedFree.tsx
│ │ ├── SftmxStatsFtmValidator.tsx
│ │ └── SftmxStatsVaults.tsx
│ ├── table
│ │ ├── SftmxTableVaults.tsx
│ │ ├── SftmxTableVaultsHeader.tsx
│ │ └── SftmxTableVaultsRow.tsx
│ └── tabs
│ │ ├── stake
│ │ ├── SftmxStakeButton.tsx
│ │ └── SftmxStakeTab.tsx
│ │ ├── unstake
│ │ ├── SftmxUnstakeButton.tsx
│ │ └── SftmxUnstakeTab.tsx
│ │ └── withdraw
│ │ ├── SftmxWithdrawButton.tsx
│ │ ├── SftmxWithdrawTab.tsx
│ │ ├── SftmxWithdrawalRequestsHeader.tsx
│ │ └── SftmxWithdrawalRequestsRow.tsx
│ ├── lib
│ ├── useSftmxGetAllWithdrawalRequests.ts
│ ├── useSftmxGetCalculatePenalty.ts
│ ├── useSftmxGetFtmxAmountForFtm.ts
│ ├── useSftmxGetStakingData.ts
│ ├── useSftmxGetWithdrawalRequests.ts
│ ├── useSftmxStake.ts
│ ├── useSftmxUnstake.ts
│ └── useSftmxWithdraw.ts
│ └── sftmx.gql
├── next-env.d.ts
├── next.config.js
├── package.json
├── pages
├── 404.tsx
├── _app-content.tsx
├── _app.tsx
├── _document.tsx
├── _error.tsx
├── api
│ ├── revalidate.ts
│ └── rpc
│ │ └── [chain]
│ │ └── routes.ts
├── compose.tsx
├── index.tsx
├── mabeets.tsx
├── pool
│ └── [poolId]
│ │ └── index.tsx
├── pools.tsx
├── recovery-exit.tsx
├── sftmx.tsx
├── swap.tsx
└── terms-of-service.tsx
├── patches
└── @ethersproject+providers+5.6.6.patch
├── public
├── favicon.ico
├── fonts
│ ├── gotham-bold-webfont.woff
│ ├── gotham-bold-webfont.woff2
│ ├── gotham-book-webfont.woff
│ ├── gotham-book-webfont.woff2
│ ├── gotham-light-webfont.woff
│ ├── gotham-light-webfont.woff2
│ ├── gotham-medium-webfont.woff
│ └── gotham-medium-webfont.woff2
├── images
│ ├── hero-image-fantom-mobile.jpg
│ ├── hero-image-fantom.jpg
│ ├── hero-image-optimism-mobile.jpg
│ └── hero-image-optimism.jpg
└── vercel.svg
├── sentry.client.config.js
├── sentry.edge.config.js
├── sentry.properties
├── sentry.server.config.js
├── styles
├── Home.module.css
├── Reliquary.module.css
├── chakraTheme.ts
├── globals.css
├── nprogress.css
└── themes
│ ├── fantomTheme.ts
│ └── optimismTheme.ts
├── tsconfig.json
├── types
└── react-table-config.d.ts
└── yarn.lock
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.github/workflows/issue-to-project.yml:
--------------------------------------------------------------------------------
1 | name: All all issues to project
2 |
3 | on:
4 | issues:
5 | types:
6 | - opened
7 |
8 | jobs:
9 | add-to-project:
10 | name: Add issue to project
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/add-to-project@v0.3.0
14 | with:
15 | project-url: https://github.com/orgs/beethovenxfi/projects/1
16 | github-token: ${{ secrets.ISSUETOPROJECT }}
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 | .next
15 | .vscode
16 |
17 | # production
18 | /build
19 |
20 | # misc
21 | .DS_Store
22 | *.pem
23 |
24 | # debug
25 | npm-debug.log*
26 | yarn-debug.log*
27 | yarn-error.log*
28 | .pnpm-debug.log*
29 |
30 | # local env files
31 | .env*.local
32 |
33 | # vercel
34 | .vercel
35 |
36 | # typescript
37 | *.tsbuildinfo
38 |
39 | .env
40 | .idea
41 |
42 | # Sentry
43 | .sentryclirc
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 120,
3 | "tabWidth": 4,
4 | "singleQuote": true,
5 | "jsxSingleQuote": false,
6 | "trailingComma": "all"
7 | }
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Beets
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Beets FE V2
2 |
--------------------------------------------------------------------------------
/assets/icons/chevron_down3.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/icons/chevron_down3.svg
--------------------------------------------------------------------------------
/assets/icons/github.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/icons/twitter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/images/beets-token-info-OP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/beets-token-info-OP.png
--------------------------------------------------------------------------------
/assets/images/beets-token-info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/beets-token-info.png
--------------------------------------------------------------------------------
/assets/images/degen-band.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/degen-band.png
--------------------------------------------------------------------------------
/assets/images/fantom-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/fantom-logo.png
--------------------------------------------------------------------------------
/assets/images/footer-OP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/footer-OP.png
--------------------------------------------------------------------------------
/assets/images/invest-masthead-image-OP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/invest-masthead-image-OP.png
--------------------------------------------------------------------------------
/assets/images/invest-masthead-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/invest-masthead-image.png
--------------------------------------------------------------------------------
/assets/images/optimism.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/images/pool-owner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/pool-owner.png
--------------------------------------------------------------------------------
/assets/images/reliquary/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/1.png
--------------------------------------------------------------------------------
/assets/images/reliquary/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/10.png
--------------------------------------------------------------------------------
/assets/images/reliquary/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/11.png
--------------------------------------------------------------------------------
/assets/images/reliquary/1x1-transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/1x1-transparent.png
--------------------------------------------------------------------------------
/assets/images/reliquary/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/2.png
--------------------------------------------------------------------------------
/assets/images/reliquary/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/3.png
--------------------------------------------------------------------------------
/assets/images/reliquary/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/4.png
--------------------------------------------------------------------------------
/assets/images/reliquary/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/5.png
--------------------------------------------------------------------------------
/assets/images/reliquary/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/6.png
--------------------------------------------------------------------------------
/assets/images/reliquary/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/7.png
--------------------------------------------------------------------------------
/assets/images/reliquary/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/8.png
--------------------------------------------------------------------------------
/assets/images/reliquary/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/9.png
--------------------------------------------------------------------------------
/assets/images/reliquary/approve-beets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/approve-beets.png
--------------------------------------------------------------------------------
/assets/images/reliquary/approve-deposit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/approve-deposit.png
--------------------------------------------------------------------------------
/assets/images/reliquary/approve-relayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/approve-relayer.png
--------------------------------------------------------------------------------
/assets/images/reliquary/approve-relic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/approve-relic.png
--------------------------------------------------------------------------------
/assets/images/reliquary/approve-vault.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/approve-vault.png
--------------------------------------------------------------------------------
/assets/images/reliquary/approve-wftm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/approve-wftm.png
--------------------------------------------------------------------------------
/assets/images/reliquary/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/background.png
--------------------------------------------------------------------------------
/assets/images/reliquary/complete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/complete.png
--------------------------------------------------------------------------------
/assets/images/reliquary/create-relic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/create-relic.png
--------------------------------------------------------------------------------
/assets/images/reliquary/finished-relic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/finished-relic.png
--------------------------------------------------------------------------------
/assets/images/reliquary/migrate-legacy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/migrate-legacy.png
--------------------------------------------------------------------------------
/assets/images/reliquary/migrate-process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/migrate-process.png
--------------------------------------------------------------------------------
/assets/images/reliquary/migrated-minted-fbeets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/migrated-minted-fbeets.png
--------------------------------------------------------------------------------
/assets/images/reliquary/unstake-fbeets.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/reliquary/unstake-fbeets.png
--------------------------------------------------------------------------------
/assets/images/rq-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/rq-1.png
--------------------------------------------------------------------------------
/assets/images/rq-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/rq-2.png
--------------------------------------------------------------------------------
/assets/images/rq-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/rq-3.png
--------------------------------------------------------------------------------
/assets/images/sFTMx-header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/sFTMx-header.png
--------------------------------------------------------------------------------
/assets/images/swap-masthead-image-OP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/swap-masthead-image-OP.png
--------------------------------------------------------------------------------
/assets/images/swap-masthead-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/swap-masthead-image.png
--------------------------------------------------------------------------------
/assets/images/why-us-OP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/why-us-OP.png
--------------------------------------------------------------------------------
/assets/images/why-us.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/images/why-us.png
--------------------------------------------------------------------------------
/assets/logo/aura_iso_colors.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/logo/aura_iso_colors.png
--------------------------------------------------------------------------------
/assets/logo/fmoney-pfp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/logo/fmoney-pfp.png
--------------------------------------------------------------------------------
/assets/logo/gyro-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/logo/gyro-white.png
--------------------------------------------------------------------------------
/assets/logo/merkl2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/assets/logo/merkl2x.png
--------------------------------------------------------------------------------
/components/animated-progress/AnimatedProgress.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps } from '@chakra-ui/layout';
2 | import { motion } from 'framer-motion';
3 | import React, { ReactNode } from 'react';
4 | import { BeetsBox } from '../box/BeetsBox';
5 |
6 | interface Props {
7 | value: number;
8 | children?: ReactNode | ReactNode[];
9 | }
10 |
11 | export default function AnimatedProgress({ value, children, ...rest }: Props & BoxProps) {
12 | return (
13 |
14 |
26 |
27 | {children}
28 |
29 |
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/components/animation/FadeInBox.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps } from '@chakra-ui/react';
2 | import { motion } from 'framer-motion';
3 |
4 | interface Props extends BoxProps {
5 | isVisible: boolean;
6 | }
7 |
8 | export function FadeInBox({ children, isVisible, ...rest }: Props) {
9 | return (
10 | <>
11 | {isVisible && (
12 |
13 | {children}
14 |
15 | )}
16 | >
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/components/animation/FadeInOutBox.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps } from '@chakra-ui/react';
2 | import { AnimatePresence, motion } from 'framer-motion';
3 |
4 | interface Props extends BoxProps {
5 | isVisible: boolean;
6 | containerWidth?: string;
7 | }
8 |
9 | export function FadeInOutBox({ children, isVisible, containerWidth, ...rest }: Props) {
10 | return (
11 |
12 | {isVisible && (
13 |
19 | {children}
20 |
21 | )}
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/components/animation/chakra.tsx:
--------------------------------------------------------------------------------
1 | import { chakra } from '@chakra-ui/system';
2 | import { isValidMotionProp, motion } from 'framer-motion';
3 |
4 | export const AnimatedBox = chakra(motion.div, {
5 | shouldForwardProp: (prop) => isValidMotionProp(prop) || prop === 'children',
6 | });
7 |
8 | export const AnimatedButton = chakra(motion.button, {
9 | shouldForwardProp: (prop) => isValidMotionProp(prop) || prop === 'children',
10 | });
--------------------------------------------------------------------------------
/components/apr-tooltip/AprText.tsx:
--------------------------------------------------------------------------------
1 | import { Text, TextProps } from '@chakra-ui/react';
2 |
3 | interface Props extends TextProps {}
4 |
5 | export function AprText({ children, ...rest }: Props) {
6 | return (
7 |
8 | {children}
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/components/avatar/WalletUserAvatar.tsx:
--------------------------------------------------------------------------------
1 | import Image from 'next/image';
2 | import BeetsSmart from '~/assets/icons/beetx-smarts.svg';
3 | import { useEarlyLudwigNft } from '~/lib/global/useEarlyLudwigNft';
4 | import { Image as ChakraImage } from '@chakra-ui/react';
5 |
6 | export function WalletUserAvatar() {
7 | const { data } = useEarlyLudwigNft();
8 |
9 | if (data) {
10 | return ;
11 | }
12 |
13 | return ;
14 | }
15 |
--------------------------------------------------------------------------------
/components/badge/PercentChangeBadge.tsx:
--------------------------------------------------------------------------------
1 | import { Badge } from '@chakra-ui/layout';
2 | import numeral from 'numeral';
3 | import { BadgeProps } from '@chakra-ui/react';
4 |
5 | interface Props extends BadgeProps {
6 | percentChange: number;
7 | }
8 |
9 | export function PercentChangeBadge({ percentChange, ...rest }: Props) {
10 | return (
11 | = 0 ? 'green' : 'red'} {...rest}>
12 | {numeral(percentChange).format('0.00%')}
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/components/box/BeetsBox.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps } from '@chakra-ui/react';
2 |
3 | interface Props extends BoxProps {}
4 |
5 | export function BeetsBox({ children, ...rest }: Props) {
6 | return (
7 |
8 | {children}
9 |
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/components/box/BeetsBoxHeader.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Flex, Text, BoxProps } from '@chakra-ui/react';
2 |
3 | export function BeetsBoxHeader(props: BoxProps) {
4 | return (
5 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/components/box/BeetsBoxLineItem.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps, Flex, FlexProps } from '@chakra-ui/react';
2 | import { ReactNode } from 'react';
3 |
4 | interface Props extends BoxProps {
5 | leftContent: ReactNode;
6 | rightContent: ReactNode;
7 | last?: boolean;
8 | center?: boolean;
9 | }
10 |
11 | export function BeetsBoxLineItem({ leftContent, rightContent, last, children, center, ...rest }: Props) {
12 | return (
13 |
14 |
15 |
16 | {leftContent}
17 |
18 | {rightContent}
19 |
20 | {children}
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/components/bridge/useBeetsBalance.tsx:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 | import { useUserBalances } from '~/lib/user/useUserBalances';
3 | import { keyBy } from 'lodash';
4 | import { parseUnits } from 'ethers/lib/utils.js';
5 |
6 | export function useBeetsBalance() {
7 | const networkConfig = useNetworkConfig();
8 | const {
9 | userBalances: balances = [],
10 | isLoading: isLoadingBalances,
11 | refetch,
12 | } = useUserBalances([networkConfig.beets.address]);
13 |
14 | const userBalancesMap = keyBy(balances, 'address');
15 | const beetsBalance = userBalancesMap[networkConfig.beets.address]?.amount || '0';
16 |
17 | return {
18 | balance: beetsBalance,
19 | isLoading: isLoadingBalances,
20 | hasBalance: parseUnits(beetsBalance, 18).gt(parseUnits('0.000001', 18)), // bridging thru stargate leaves some dust
21 | refetch,
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/components/button/BeetsBatchRelayerApprovalButton.tsx:
--------------------------------------------------------------------------------
1 | import { BeetsSubmitTransactionButton } from '~/components/button/BeetsSubmitTransactionButton';
2 | import { useApproveBatchRelayer } from '~/lib/util/useApproveBatchRelayer';
3 |
4 | interface Props {
5 | contractToApprove?: string;
6 | onConfirmed?: () => void;
7 | onPending?: () => void;
8 | onSubmitting?: () => void;
9 | onCanceled?: () => void;
10 | isDisabled?: boolean;
11 | size?: string;
12 | buttonText?: string;
13 | }
14 |
15 | export function BeetsBatchRelayerApprovalButton({ buttonText, ...rest }: Props) {
16 | const { approve, ...query } = useApproveBatchRelayer();
17 |
18 | return (
19 | {
23 | approve();
24 | }}
25 | {...rest}
26 | borderColor="beets.green"
27 | _focus={{ boxShadow: 'none' }}
28 | submittingText="Confirm..."
29 | pendingText="Waiting..."
30 | >
31 | {buttonText ? buttonText : 'Approve Batch Relayer'}
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/components/button/BeetsMinterApprovalButton.tsx:
--------------------------------------------------------------------------------
1 | import { BeetsSubmitTransactionButton } from '~/components/button/BeetsSubmitTransactionButton';
2 | import { useApproveMinter } from '~/lib/util/useApproveMinter';
3 |
4 | interface Props {
5 | contractToApprove?: string;
6 | onConfirmed?: () => void;
7 | onPending?: () => void;
8 | onSubmitting?: () => void;
9 | onCanceled?: () => void;
10 | isDisabled?: boolean;
11 | size?: string;
12 | buttonText?: string;
13 | }
14 |
15 | export function BeetsMinterApprovalButton({ buttonText, ...rest }: Props) {
16 | const { approve, ...query } = useApproveMinter();
17 |
18 | return (
19 | {
23 | approve();
24 | }}
25 | {...rest}
26 | borderColor="beets.green"
27 | _focus={{ boxShadow: 'none' }}
28 | submittingText="Confirm..."
29 | pendingText="Waiting..."
30 | >
31 | {buttonText ? buttonText : 'Approve Batch Relayer for minting'}
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/components/button/BeetsTokenApprovalButton.tsx:
--------------------------------------------------------------------------------
1 | import { TokenBaseWithAmount } from '~/lib/services/token/token-types';
2 | import { useApproveToken } from '~/lib/util/useApproveToken';
3 | import { BeetsSubmitTransactionButton } from '~/components/button/BeetsSubmitTransactionButton';
4 | import { networkConfig } from '~/lib/config/network-config';
5 |
6 | interface Props {
7 | tokenWithAmount: TokenBaseWithAmount;
8 | contractToApprove?: string;
9 | onConfirmed?: () => void;
10 | onPending?: () => void;
11 | onSubmitting?: () => void;
12 | onCanceled?: () => void;
13 | isDisabled?: boolean;
14 | size?: string;
15 | inline?: boolean;
16 | isLoading?: boolean;
17 | }
18 |
19 | export function BeetsTokenApprovalButton({
20 | tokenWithAmount,
21 | contractToApprove = networkConfig.balancer.vault,
22 | ...rest
23 | }: Props) {
24 | const { approve, ...query } = useApproveToken(tokenWithAmount);
25 |
26 | return (
27 | {
31 | approve(contractToApprove);
32 | }}
33 | {...rest}
34 | >
35 | Approve {tokenWithAmount.symbol}
36 |
37 | );
38 | }
39 |
--------------------------------------------------------------------------------
/components/card/CardRow.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Flex, FlexProps } from '@chakra-ui/react';
2 |
3 | export function CardRow(props: FlexProps) {
4 | return ;
5 | }
6 |
--------------------------------------------------------------------------------
/components/fallback/FallbackPlaceholder.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Spinner } from '@chakra-ui/react';
2 |
3 | export function FallbackPlaceholder() {
4 | return (
5 |
6 |
7 | Loading...
8 |
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/components/icons/IconGithub.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Icon, IconProps } from '@chakra-ui/react';
3 |
4 | export function IconGithub(props: IconProps) {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/components/icons/IconGlobe.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Icon, IconProps } from '@chakra-ui/react';
3 |
4 | export function IconGlobe(props: IconProps) {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/components/icons/IconTelegram.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Icon, IconProps } from '@chakra-ui/react';
3 |
4 | export function IconTelegram(props: IconProps) {
5 | return (
6 |
7 |
8 |
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/components/icons/IconTwitter.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Icon, IconProps } from '@chakra-ui/react';
3 |
4 | export function IconTwitter(props: IconProps) {
5 | return (
6 |
7 |
8 |
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/components/inputs/PresetSelector.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from '@chakra-ui/button';
2 | import { HStack } from '@chakra-ui/layout';
3 |
4 | type Preset = {
5 | label: string;
6 | value: number;
7 | };
8 | interface Props {
9 | onPresetSelected: (preset: number) => void;
10 | presets?: Preset[];
11 | }
12 |
13 | const defaultPresets = [
14 | {
15 | label: '25%',
16 | value: 0.25,
17 | },
18 | {
19 | label: '50%',
20 | value: 0.5,
21 | },
22 | {
23 | label: '75%',
24 | value: 0.75,
25 | },
26 | {
27 | label: '100%',
28 | value: 1,
29 | },
30 | ];
31 | export default function PresetSelector({ onPresetSelected, presets = defaultPresets }: Props) {
32 | const handlePresetSelected = (preset: number) => () => {
33 | onPresetSelected(preset);
34 | };
35 | return (
36 |
37 | {presets.map((preset) => (
38 |
47 | ))}
48 |
49 | );
50 | }
51 |
--------------------------------------------------------------------------------
/components/link/NextLink.tsx:
--------------------------------------------------------------------------------
1 | import { Link as ChakraLink, LinkProps as ChakraLinkProps, LinkOverlay, LinkOverlayProps } from '@chakra-ui/react';
2 | import Link, { LinkProps } from 'next/link';
3 | import React from 'react';
4 |
5 | export function NextLink({
6 | children,
7 | chakraProps,
8 | ...rest
9 | }: React.PropsWithChildren & { chakraProps?: ChakraLinkProps }) {
10 | return (
11 |
12 | {children}
13 |
14 | );
15 | }
16 |
17 | export function NextLinkOverlay({
18 | children,
19 | chakraProps,
20 | ...rest
21 | }: React.PropsWithChildren & { chakraProps?: LinkOverlayProps }) {
22 | return (
23 |
24 | {children}
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/components/masthead/PageMasthead.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Flex, Text } from '@chakra-ui/react';
2 | import { ReactNode } from 'react';
3 |
4 | interface Props {
5 | title: string;
6 | image: ReactNode;
7 | }
8 |
9 | export function PageMasthead({ title, image }: Props) {
10 | return (
11 |
17 |
18 | {title}
19 |
20 |
21 | {image}
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/components/modal/ModalSectionHeadline.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps, Text } from '@chakra-ui/react';
2 |
3 | interface Props extends BoxProps {
4 | headline: string;
5 | description?: string;
6 | }
7 |
8 | export function ModalSectionHeadline({ headline, description, ...rest }: Props) {
9 | return (
10 |
11 |
12 | {headline}
13 |
14 | {description}
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/components/pool-badge/assets/badge-experimental.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/badge-experimental.gif
--------------------------------------------------------------------------------
/components/pool-badge/assets/boosted-by-beefy-exactly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/boosted-by-beefy-exactly.png
--------------------------------------------------------------------------------
/components/pool-badge/assets/built-by-gyroscope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/built-by-gyroscope.png
--------------------------------------------------------------------------------
/components/pool-badge/assets/overnight-boosted-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/overnight-boosted-small.png
--------------------------------------------------------------------------------
/components/pool-badge/assets/reaper-aave-boosted-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/reaper-aave-boosted-small.png
--------------------------------------------------------------------------------
/components/pool-badge/assets/reaper-aave-granary-boosted-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/reaper-aave-granary-boosted-small.png
--------------------------------------------------------------------------------
/components/pool-badge/assets/reaper-boosted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/reaper-boosted.png
--------------------------------------------------------------------------------
/components/pool-badge/assets/reaper-sonne-boosted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/components/pool-badge/assets/reaper-sonne-boosted.png
--------------------------------------------------------------------------------
/components/popup-menu/TextButtonPopupMenu.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/react';
2 | import { Check } from 'react-feather';
3 |
4 | interface Props {
5 | buttonText: string;
6 | items: {
7 | label: string;
8 | selected?: boolean;
9 | onClick: () => void;
10 | }[];
11 | }
12 |
13 | export function TextButtonPopupMenu({ buttonText, items }: Props) {
14 | return (
15 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/components/providers/Compose.tsx:
--------------------------------------------------------------------------------
1 | export type ProviderWithProps = [React.JSXElementConstructor>, any];
2 | interface Props {
3 | providers: Array;
4 | children: React.ReactNode;
5 |
6 | }
7 |
8 | export default function Compose(props: Props) {
9 | const { providers = [], children } = props;
10 |
11 | return (
12 | <>
13 | {providers.reduceRight((acc, prov) => {
14 | const Provider = prov[0];
15 | return {acc};
16 | }, children)}
17 | >
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/components/tabs/BeetsTab.tsx:
--------------------------------------------------------------------------------
1 | import { Button, TabProps, HStack, Tab, Text, useTab, useMultiStyleConfig, Box } from '@chakra-ui/react';
2 | import { AnimatePresence } from 'framer-motion';
3 | import { forwardRef } from 'react';
4 | import { Eye } from 'react-feather';
5 | import { AnimatedBox } from '~/components/animation/chakra';
6 |
7 | const BeetsTab = forwardRef((props: { children: any } & TabProps, ref: any) => {
8 | const tabProps = useTab({ ...props, ref });
9 | const isSelected = !!tabProps['aria-selected'];
10 |
11 | return (
12 |
30 | );
31 | });
32 |
33 | BeetsTab.displayName = 'BeetsTab';
34 | export default BeetsTab;
35 |
--------------------------------------------------------------------------------
/components/token-select/TokenActionRow.tsx:
--------------------------------------------------------------------------------
1 | import { Button, ButtonProps } from '@chakra-ui/button';
2 | import { Box, HStack, Text } from '@chakra-ui/layout';
3 | import TokenAvatar from '~/components/token/TokenAvatar';
4 | import { TokenBase } from '~/lib/services/token/token-types';
5 | import { LinkProps } from '@chakra-ui/react';
6 |
7 | type TokenRowProps = TokenBase & {
8 | index: number;
9 | action: 'import' | 'remove';
10 | };
11 |
12 | export function TokenActionRow({ symbol, address, onClick, action }: TokenRowProps & ButtonProps & LinkProps) {
13 | return (
14 |
15 |
16 |
17 |
18 | {symbol}
19 |
20 |
21 |
24 |
25 |
26 |
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/components/token-select/TokenSelectSearchInput.tsx:
--------------------------------------------------------------------------------
1 | import { forwardRef, Input, InputGroup, InputLeftElement, useTheme } from '@chakra-ui/react';
2 | import { Search } from 'react-feather';
3 |
4 | interface Props {
5 | placeholder: string;
6 | value: string;
7 | setValue: (value: string) => void;
8 | }
9 |
10 | export const TokenSelectSearchInput = forwardRef(({ value, setValue, placeholder }: Props, ref) => {
11 | const { colors } = useTheme();
12 |
13 | return (
14 |
15 |
16 |
17 |
18 | setValue(e.currentTarget.value)}
25 | />
26 |
27 | );
28 | });
29 |
--------------------------------------------------------------------------------
/components/token/TokenAmountPill.tsx:
--------------------------------------------------------------------------------
1 | import { BeetsBox } from '~/components/box/BeetsBox';
2 | import TokenAvatar from '~/components/token/TokenAvatar';
3 | import { Flex, Text, BoxProps } from '@chakra-ui/react';
4 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
5 | import { tokenFormatAmount, tokenFormatAmountPrecise } from '~/lib/services/token/token-util';
6 |
7 | interface Props extends BoxProps {
8 | address: string;
9 | amount: AmountHumanReadable;
10 | amountFormat?: 'standard' | 'precise';
11 | }
12 |
13 | export function TokenAmountPill({ address, amount, amountFormat = 'standard', ...rest }: Props) {
14 | return (
15 |
16 |
17 |
18 |
19 | {amountFormat === 'precise' ? tokenFormatAmountPrecise(amount) : tokenFormatAmount(amount)}
20 |
21 |
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/components/token/TokenAvatar.tsx:
--------------------------------------------------------------------------------
1 | import { Avatar, AvatarProps, Circle } from '@chakra-ui/react';
2 | import { useGetTokens } from '~/lib/global/useToken';
3 | import Jazzicon, { jsNumberForAddress } from 'react-jazzicon';
4 | import { AddressZero } from '@ethersproject/constants';
5 |
6 | interface Props extends AvatarProps {
7 | address?: string | null;
8 | logoURI?: string;
9 | }
10 |
11 | function TokenAvatar({ address, size, logoURI, ...rest }: Props) {
12 | const { getToken } = useGetTokens();
13 | const token = address ? getToken(address) : null;
14 |
15 | return (
16 |
24 | ) : (
25 |
29 | )
30 | }
31 | />
32 | );
33 | }
34 |
35 | export default TokenAvatar;
36 |
--------------------------------------------------------------------------------
/components/tooltip/BeetsTooltip.tsx:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from 'react';
2 | import { Box, HStack, Text } from '@chakra-ui/layout';
3 | import { Tooltip } from '@chakra-ui/tooltip';
4 | import BeetsThinking from '~/assets/icons/beetx-thinking.svg';
5 | import Image from 'next/image';
6 |
7 | interface Props {
8 | children: ReactNode | ReactNode[];
9 | label: ReactNode | ReactNode[] | null;
10 | noImage?: boolean;
11 | hasArrow?: boolean;
12 | }
13 |
14 | function BeetsTooltipLabel({ label, noImage }: { label: ReactNode | ReactNode[]; noImage: boolean }) {
15 | return (
16 |
17 | {!noImage && (
18 |
19 |
20 |
21 | )}
22 | {label}
23 |
24 | );
25 | }
26 |
27 | export default function BeetsTooltip({ children, label, noImage, hasArrow = false }: Props) {
28 | if (!label) return <>{children}>;
29 |
30 | return (
31 | }
37 | hasArrow={hasArrow}
38 | >
39 | {children}
40 |
41 | );
42 | }
43 |
--------------------------------------------------------------------------------
/components/typography/BeetsHeadline.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps } from '@chakra-ui/react';
2 | import { ReactNode } from 'react';
3 |
4 | interface Props extends BoxProps {
5 | children: ReactNode;
6 | }
7 |
8 | export function BeetsHeadline({ children, ...rest }: Props) {
9 | return (
10 |
11 | {children}
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/components/typography/BeetsSubHeadline.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps, Text } from '@chakra-ui/react';
2 | import { ReactNode } from 'react';
3 |
4 | interface Props extends BoxProps {
5 | children: ReactNode;
6 | }
7 |
8 | export function BeetsSubHeadline({ children, ...rest }: Props) {
9 | return (
10 |
11 | {children}
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/components/user-warning/UserWarning.tsx:
--------------------------------------------------------------------------------
1 | import { useUserData } from '~/lib/user/useUserData';
2 | import { ToastType, useToast } from '~/components/toast/BeetsToast';
3 | import { useEffect } from 'react';
4 | import { Box, Button, HStack, Link } from '@chakra-ui/react';
5 | import { networkConfig } from '~/lib/config/network-config';
6 |
7 | export function UserWarning() {
8 | const { usdBalanceForPool } = useUserData();
9 | const { showToast } = useToast();
10 |
11 | const poolList = Object.keys(networkConfig.warnings.poolList);
12 | const userHasFundsAtRisk = poolList.find((pooliD) => usdBalanceForPool(pooliD) > 0);
13 |
14 | useEffect(() => {
15 | if (userHasFundsAtRisk) {
16 | showToast({
17 | id: 'user-funds-alert',
18 | type: ToastType.Warn,
19 | content: (
20 |
21 |
22 | You are invested in a pool with a known vulnerability. Please remove liquidity from the
23 | affected pool(s) immediately.
24 |
25 |
26 | ),
27 | });
28 | }
29 | }, [userHasFundsAtRisk]);
30 |
31 | return null;
32 | }
33 |
--------------------------------------------------------------------------------
/declarations.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'react-virtual-list';
--------------------------------------------------------------------------------
/lib/abi/BasePoolFactory.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "anonymous": false,
4 | "inputs": [
5 | {
6 | "indexed": true,
7 | "internalType": "address",
8 | "name": "pool",
9 | "type": "address"
10 | }
11 | ],
12 | "name": "PoolRegistered",
13 | "type": "event"
14 | },
15 | {
16 | "inputs": [],
17 | "name": "vault",
18 | "outputs": [
19 | {
20 | "internalType": "contract IVault",
21 | "name": "",
22 | "type": "address"
23 | }
24 | ],
25 | "stateMutability": "view",
26 | "type": "function"
27 | }
28 | ]
29 |
--------------------------------------------------------------------------------
/lib/abi/BatchRelayer.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "contract IVault",
6 | "name": "vault",
7 | "type": "address"
8 | },
9 | {
10 | "internalType": "address",
11 | "name": "libraryAddress",
12 | "type": "address"
13 | }
14 | ],
15 | "stateMutability": "nonpayable",
16 | "type": "constructor"
17 | },
18 | {
19 | "inputs": [],
20 | "name": "getLibrary",
21 | "outputs": [
22 | {
23 | "internalType": "address",
24 | "name": "",
25 | "type": "address"
26 | }
27 | ],
28 | "stateMutability": "view",
29 | "type": "function"
30 | },
31 | {
32 | "inputs": [],
33 | "name": "getVault",
34 | "outputs": [
35 | {
36 | "internalType": "contract IVault",
37 | "name": "",
38 | "type": "address"
39 | }
40 | ],
41 | "stateMutability": "view",
42 | "type": "function"
43 | },
44 | {
45 | "inputs": [
46 | {
47 | "internalType": "bytes[]",
48 | "name": "data",
49 | "type": "bytes[]"
50 | }
51 | ],
52 | "name": "multicall",
53 | "outputs": [
54 | {
55 | "internalType": "bytes[]",
56 | "name": "results",
57 | "type": "bytes[]"
58 | }
59 | ],
60 | "stateMutability": "payable",
61 | "type": "function"
62 | },
63 | {
64 | "stateMutability": "payable",
65 | "type": "receive"
66 | }
67 | ]
68 |
--------------------------------------------------------------------------------
/lib/abi/BatchRelayerLibrary.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "name": "getEntrypoint",
5 | "outputs": [{ "internalType": "contract IBalancerRelayer", "name": "", "type": "address" }],
6 | "stateMutability": "view",
7 | "type": "function"
8 | },
9 | {
10 | "inputs": [],
11 | "name": "getVault",
12 | "outputs": [{ "internalType": "contract IVault", "name": "", "type": "address" }],
13 | "stateMutability": "view",
14 | "type": "function"
15 | },
16 | {
17 | "inputs": [{ "internalType": "uint256", "name": "ref", "type": "uint256" }],
18 | "name": "peekChainedReferenceValue",
19 | "outputs": [{ "internalType": "uint256", "name": "value", "type": "uint256" }],
20 | "stateMutability": "view",
21 | "type": "function"
22 | }
23 | ]
24 |
--------------------------------------------------------------------------------
/lib/abi/BeethovenCheckpointer.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [{ "internalType": "address[]", "name": "gauges_to_checkpoint", "type": "address[]" }],
4 | "name": "checkpoint_my_gauges",
5 | "outputs": [],
6 | "stateMutability": "nonpayable",
7 | "type": "function"
8 | },
9 | {
10 | "inputs": [
11 | { "internalType": "address", "name": "user", "type": "address" },
12 | { "internalType": "address[]", "name": "gauges_to_checkpoint", "type": "address[]" }
13 | ],
14 | "name": "checkpoint_user_gauges",
15 | "outputs": [],
16 | "stateMutability": "nonpayable",
17 | "type": "function"
18 | }
19 | ]
20 |
--------------------------------------------------------------------------------
/lib/abi/ChildChainGaugeRewardHelper.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [],
4 | "name": "CLAIM_FREQUENCY",
5 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
6 | "stateMutability": "view",
7 | "type": "function"
8 | },
9 | {
10 | "inputs": [],
11 | "name": "CLAIM_SIG",
12 | "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }],
13 | "stateMutability": "view",
14 | "type": "function"
15 | },
16 | {
17 | "inputs": [
18 | {
19 | "internalType": "contract IRewardsOnlyGauge",
20 | "name": "gauge",
21 | "type": "address"
22 | },
23 | { "internalType": "address", "name": "user", "type": "address" }
24 | ],
25 | "name": "claimRewards",
26 | "outputs": [],
27 | "stateMutability": "nonpayable",
28 | "type": "function"
29 | },
30 | {
31 | "inputs": [
32 | {
33 | "internalType": "contract IRewardsOnlyGauge",
34 | "name": "gauge",
35 | "type": "address"
36 | },
37 | { "internalType": "address", "name": "user", "type": "address" },
38 | { "internalType": "address", "name": "token", "type": "address" }
39 | ],
40 | "name": "pendingRewards",
41 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
42 | "stateMutability": "nonpayable",
43 | "type": "function"
44 | }
45 | ]
46 |
--------------------------------------------------------------------------------
/lib/abi/LinearPoolRebalancer.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | { "internalType": "contract IVault", "name": "vault", "type": "address" },
5 | { "internalType": "contract IBalancerQueries", "name": "queries", "type": "address" }
6 | ],
7 | "stateMutability": "nonpayable",
8 | "type": "constructor"
9 | },
10 | {
11 | "inputs": [],
12 | "name": "getPool",
13 | "outputs": [{ "internalType": "contract ILinearPool", "name": "", "type": "address" }],
14 | "stateMutability": "view",
15 | "type": "function"
16 | },
17 | {
18 | "inputs": [{ "internalType": "address", "name": "recipient", "type": "address" }],
19 | "name": "rebalance",
20 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
21 | "stateMutability": "nonpayable",
22 | "type": "function"
23 | },
24 | {
25 | "inputs": [
26 | { "internalType": "address", "name": "recipient", "type": "address" },
27 | { "internalType": "uint256", "name": "extraMain", "type": "uint256" }
28 | ],
29 | "name": "rebalanceWithExtraMain",
30 | "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
31 | "stateMutability": "nonpayable",
32 | "type": "function"
33 | }
34 | ]
35 |
--------------------------------------------------------------------------------
/lib/abi/StaticATokenRateProvider.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "contract IStaticAToken",
6 | "name": "_waToken",
7 | "type": "address"
8 | }
9 | ],
10 | "stateMutability": "nonpayable",
11 | "type": "constructor"
12 | },
13 | {
14 | "inputs": [],
15 | "name": "getRate",
16 | "outputs": [
17 | {
18 | "internalType": "uint256",
19 | "name": "",
20 | "type": "uint256"
21 | }
22 | ],
23 | "stateMutability": "view",
24 | "type": "function"
25 | },
26 | {
27 | "inputs": [],
28 | "name": "waToken",
29 | "outputs": [
30 | {
31 | "internalType": "contract IStaticAToken",
32 | "name": "",
33 | "type": "address"
34 | }
35 | ],
36 | "stateMutability": "view",
37 | "type": "function"
38 | }
39 | ]
40 |
--------------------------------------------------------------------------------
/lib/config/network-config.ts:
--------------------------------------------------------------------------------
1 | import { NetworkConfig } from '~/lib/config/network-config-type';
2 | import { fantomNetworkConfig } from '~/lib/config/fantom';
3 | import { optimismNetworkConfig } from '~/lib/config/optimism';
4 |
5 | const AllNetworkConfigs: { [chainId: string]: NetworkConfig } = {
6 | '250': fantomNetworkConfig,
7 | '10': optimismNetworkConfig,
8 | };
9 |
10 | export const networkConfig = AllNetworkConfigs[process.env.NEXT_PUBLIC_CHAIN_ID || '250'];
11 |
12 | export const networkList = [
13 | {
14 | name: fantomNetworkConfig.networkShortName,
15 | chainId: fantomNetworkConfig.chainId,
16 | url: 'https://beets.fi',
17 | iconUrl: fantomNetworkConfig.eth.iconUrl,
18 | },
19 | {
20 | name: optimismNetworkConfig.networkShortName,
21 | chainId: optimismNetworkConfig.chainId,
22 | url: 'https://op.beets.fi',
23 | iconUrl: optimismNetworkConfig.eth.iconUrl,
24 | },
25 | ];
26 |
--------------------------------------------------------------------------------
/lib/global/constants.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | subgraphs: {
3 | 'mainnet-gauge': 'https://api.studio.thegraph.com/query/75376/balancer-gauges/version/latest',
4 | 'optimism-gauge': 'https://api.studio.thegraph.com/query/75376/balancer-gauges-optimism/version/latest',
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/lib/global/useMasterChefHarvestAllRewards.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import BeethovenxMasterChefAbi from '~/lib/abi/BeethovenxMasterChef.json';
3 | import { useUserAccount } from '~/lib/user/useUserAccount';
4 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
5 |
6 | export function useMasterChefHarvestAllRewards() {
7 | const networkConfig = useNetworkConfig();
8 | const { userAddress } = useUserAccount();
9 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
10 | config: {
11 | addressOrName: networkConfig.masterChefContractAddress,
12 | contractInterface: BeethovenxMasterChefAbi,
13 | functionName: 'harvestAll',
14 | },
15 | transactionType: 'HARVEST',
16 | });
17 |
18 | function harvestAll(farmIds: string[]) {
19 | submit({
20 | args: [farmIds, userAddress],
21 | toastText: 'Harvest all pending rewards',
22 | });
23 | }
24 |
25 | return {
26 | harvestAll,
27 | ...rest,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/lib/global/useNetworkConfig.ts:
--------------------------------------------------------------------------------
1 | import { networkConfig } from '~/lib/config/network-config';
2 |
3 | export function useNetworkConfig() {
4 | return networkConfig;
5 | }
6 |
--------------------------------------------------------------------------------
/lib/global/useOldBeetsBalance.ts:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 | import { useUserBalances } from '~/lib/user/useUserBalances';
3 | import { keyBy } from 'lodash';
4 |
5 | export function useOldBeetsBalance() {
6 | const networkConfig = useNetworkConfig();
7 | const { userBalances: balances = [], isLoading: isLoadingBalances } = useUserBalances([
8 | networkConfig.beets.oldAddress,
9 | ]);
10 |
11 | const userBalancesMap = keyBy(balances, 'address');
12 | const oldBeetsBalance = userBalancesMap[networkConfig.beets.oldAddress]?.amount || '0';
13 |
14 | return {
15 | balance: oldBeetsBalance,
16 | isLoading: isLoadingBalances,
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/lib/global/useSlippage.ts:
--------------------------------------------------------------------------------
1 | import { makeVar, useReactiveVar } from '@apollo/client';
2 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
3 |
4 | const SLIPPAGE_CACHE_KEY = 'SLIPPAGE';
5 | const cached = typeof window !== 'undefined' ? localStorage.getItem(SLIPPAGE_CACHE_KEY) : null;
6 |
7 | const slippageVar = makeVar(cached || '0.005');
8 |
9 | export function useSlippage() {
10 | const slippage = useReactiveVar(slippageVar);
11 | const slippageDifference = 1 - parseFloat(slippage);
12 | const slippageAddition = 1 + parseFloat(slippage);
13 |
14 | function setSlippage(amount: AmountHumanReadable) {
15 | slippageVar(amount);
16 |
17 | localStorage.setItem(SLIPPAGE_CACHE_KEY, amount);
18 | }
19 |
20 | return {
21 | slippage,
22 | slippageDifference,
23 | slippageAddition,
24 | setSlippage,
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/lib/global/useSubgraphQuery.ts:
--------------------------------------------------------------------------------
1 | import { DocumentNode } from 'graphql';
2 | import { QueryKey, QueryOptions, UseQueryOptions, useQuery } from 'react-query';
3 | import axios from 'axios';
4 |
5 | import constants from '~/lib/global/constants';
6 |
7 | export type SupportedSubgraphs = 'mainnet-gauge' | 'optimism-gauge';
8 | export type SubgraphResponse = {
9 | data: T;
10 | };
11 |
12 | export default function useSubgraphQuery<
13 | T,
14 | TQueryFnData = T,
15 | TError = unknown,
16 | TData = T,
17 | TQueryKey extends QueryKey = QueryKey,
18 | >(
19 | subgraph: SupportedSubgraphs,
20 | query: DocumentNode,
21 | variables: any,
22 | options: Omit, 'queryKey' | 'queryFn'> = {},
23 | ) {
24 | const queryString = query.loc?.source.body;
25 | const url = constants.subgraphs[subgraph];
26 | const queryInstance = useQuery(
27 | ['subgraph-query', { subgraph, query: queryString, variables }] as any,
28 | async () => {
29 | const response = await axios.post>(url, {
30 | query: queryString,
31 | variables,
32 | });
33 |
34 | return response.data.data;
35 | },
36 | options as any,
37 | );
38 |
39 | return queryInstance;
40 | }
41 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/aave-wrapping.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import aaveWrappingAbi from '~/lib/abi/AaveWrapping.json';
3 | import { EncodeUnwrapAaveStaticTokenInput } from '~/lib/services/batch-relayer/relayer-types';
4 |
5 | export class AaveWrappingService {
6 | public encodeUnwrap(params: EncodeUnwrapAaveStaticTokenInput): string {
7 | const aaveWrappingLibrary = new Interface(aaveWrappingAbi);
8 |
9 | return aaveWrappingLibrary.encodeFunctionData('unwrapAaveStaticToken', [
10 | params.staticToken,
11 | params.sender,
12 | params.recipient,
13 | params.amount,
14 | params.toUnderlying,
15 | params.outputReferences,
16 | ]);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/boo-mirror-world-staking.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import booMirrorWorldStakingAbi from '~/lib/abi/BooMirrorWorldStaking.json';
3 | import {
4 | EncodeBooMirrorWorldEnterInput,
5 | EncodeBooMirrorWorldLeaveInput,
6 | } from '~/lib/services/batch-relayer/relayer-types';
7 |
8 | export class BooMirrorWorldStakingService {
9 | public encodeEnter(params: EncodeBooMirrorWorldEnterInput): string {
10 | const booMirrorWorldStakingLibrary = new Interface(booMirrorWorldStakingAbi);
11 |
12 | return booMirrorWorldStakingLibrary.encodeFunctionData('booMirrorWorldEnter', [
13 | params.sender,
14 | params.recipient,
15 | params.amount,
16 | params.outputReference,
17 | ]);
18 | }
19 |
20 | public encodeLeave(params: EncodeBooMirrorWorldLeaveInput): string {
21 | const booMirrorWorldStakingLibrary = new Interface(booMirrorWorldStakingAbi);
22 |
23 | return booMirrorWorldStakingLibrary.encodeFunctionData('booMirrorWorldLeave', [
24 | params.sender,
25 | params.recipient,
26 | params.amount,
27 | params.outputReference,
28 | ]);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/erc4626-wrapping.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import Erc4626WrappingAbi from '~/lib/abi/Erc4626Wrapping.json';
3 | import { EncodeUnwrapErc4626Input, EncodeWrapErc4626Input } from '~/lib/services/batch-relayer/relayer-types';
4 |
5 | export class Erc4626WrappingService {
6 | public encodeWrap(params: EncodeWrapErc4626Input): string {
7 | const erc4626WrappingLibrary = new Interface(Erc4626WrappingAbi);
8 |
9 | return erc4626WrappingLibrary.encodeFunctionData('wrapERC4626', [
10 | params.wrappedToken,
11 | params.sender,
12 | params.recipient,
13 | params.amount,
14 | params.outputReference,
15 | ]);
16 | }
17 |
18 | public encodeUnwrap(params: EncodeUnwrapErc4626Input): string {
19 | const erc4626WrappingLibrary = new Interface(Erc4626WrappingAbi);
20 |
21 | return erc4626WrappingLibrary.encodeFunctionData('unwrapERC4626', [
22 | params.wrappedToken,
23 | params.sender,
24 | params.recipient,
25 | params.amount,
26 | params.outputReference,
27 | ]);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/fbeets-bar-staking.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import fBeetsBarStakingAbi from '~/lib/abi/FBeetsBarStaking.json';
3 | import { EncodeFBeetsBarEnterInput, EncodeFBeetsBarLeaveInput } from '~/lib/services/batch-relayer/relayer-types';
4 |
5 | export class FBeetsBarStakingService {
6 | public encodeEnter(params: EncodeFBeetsBarEnterInput): string {
7 | const fBeetsBarStakingLibrary = new Interface(fBeetsBarStakingAbi);
8 |
9 | return fBeetsBarStakingLibrary.encodeFunctionData('fBeetsBarEnter', [
10 | params.sender,
11 | params.recipient,
12 | params.amount,
13 | params.outputReference,
14 | ]);
15 | }
16 |
17 | public encodeLeave(params: EncodeFBeetsBarLeaveInput): string {
18 | const fBeetsBarStakingLibrary = new Interface(fBeetsBarStakingAbi);
19 |
20 | return fBeetsBarStakingLibrary.encodeFunctionData('fBeetsBarLeave', [
21 | params.sender,
22 | params.recipient,
23 | params.amount,
24 | params.outputReference,
25 | ]);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/masterchef-staking.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import MasterChefStakingAbi from '~/lib/abi/MasterChefStaking.json';
3 | import {
4 | EncodeMasterChefDepositInput,
5 | EncodeMasterChefWithdrawInput,
6 | } from '~/lib/services/batch-relayer/relayer-types';
7 |
8 | export class MasterChefStakingService {
9 | public encodeDeposit(params: EncodeMasterChefDepositInput): string {
10 | const masterChefStakingLibrary = new Interface(MasterChefStakingAbi);
11 |
12 | return masterChefStakingLibrary.encodeFunctionData('masterChefDeposit', [
13 | params.sender,
14 | params.recipient,
15 | params.token,
16 | params.pid,
17 | params.amount,
18 | params.outputReference,
19 | ]);
20 | }
21 |
22 | public encodeWithdraw(params: EncodeMasterChefWithdrawInput): string {
23 | const masterChefStakingLibrary = new Interface(MasterChefStakingAbi);
24 |
25 | return masterChefStakingLibrary.encodeFunctionData('masterChefWithdraw', [
26 | params.recipient,
27 | params.pid,
28 | params.amount,
29 | params.outputReference,
30 | ]);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/reaper-wrapping.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import ReaperWrappingAbi from '~/lib/abi/ReaperWrapping.json';
3 | import {
4 | EncodeWrapReaperVaultTokenInput,
5 | EncodeUnwrapReaperVaultTokenInput,
6 | } from '~/lib/services/batch-relayer/relayer-types';
7 |
8 | export class ReaperWrappingService {
9 | public encodeWrap(params: EncodeWrapReaperVaultTokenInput): string {
10 | const reaperWrappingLibrary = new Interface(ReaperWrappingAbi);
11 |
12 | return reaperWrappingLibrary.encodeFunctionData('wrapReaperVaultToken', [
13 | params.vaultToken,
14 | params.sender,
15 | params.recipient,
16 | params.amount,
17 | params.outputReference,
18 | ]);
19 | }
20 |
21 | public encodeUnwrap(params: EncodeUnwrapReaperVaultTokenInput): string {
22 | const reaperWrappingLibrary = new Interface(ReaperWrappingAbi);
23 |
24 | return reaperWrappingLibrary.encodeFunctionData('unwrapReaperVaultToken', [
25 | params.vaultToken,
26 | params.sender,
27 | params.recipient,
28 | params.amount,
29 | params.outputReference,
30 | ]);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/tarot-supply-vault.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import tarotWrappingAbi from '~/lib/abi/TarotWrapping.json';
3 | import { EncodeTarotEnterInput, EncodeTarotLeaveInput } from '~/lib/services/batch-relayer/relayer-types';
4 |
5 | export class TarotSupplyVaultService {
6 | public encodeEnter(params: EncodeTarotEnterInput): string {
7 | const tarotWrappingLibrary = new Interface(tarotWrappingAbi);
8 |
9 | return tarotWrappingLibrary.encodeFunctionData('tarotSupplyVaultEnter', [
10 | params.supplyVault,
11 | params.sender,
12 | params.recipient,
13 | params.amount,
14 | params.outputReference,
15 | ]);
16 | }
17 |
18 | public encodeLeave(params: EncodeTarotLeaveInput): string {
19 | const tarotWrappingLibrary = new Interface(tarotWrappingAbi);
20 |
21 | return tarotWrappingLibrary.encodeFunctionData('tarotSupplyVaultLeave', [
22 | params.supplyVault,
23 | params.sender,
24 | params.recipient,
25 | params.amount,
26 | params.outputReference,
27 | ]);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/services/batch-relayer/extensions/yearn-wrapping.service.ts:
--------------------------------------------------------------------------------
1 | import { Interface } from '@ethersproject/abi';
2 | import YearnWrappingAbi from '~/lib/abi/YearnWrapping.json';
3 | import { EncodeUnwrapYearnVaultTokenInput } from '~/lib/services/batch-relayer/relayer-types';
4 |
5 | export class YearnWrappingService {
6 | public encodeWrap(params: EncodeUnwrapYearnVaultTokenInput): string {
7 | const yearnWrappingLibrary = new Interface(YearnWrappingAbi);
8 |
9 | return yearnWrappingLibrary.encodeFunctionData('wrapYearnVaultToken', [
10 | params.vaultToken,
11 | params.sender,
12 | params.recipient,
13 | params.amount,
14 | params.outputReference,
15 | ]);
16 | }
17 |
18 | public encodeUnwrap(params: EncodeUnwrapYearnVaultTokenInput): string {
19 | const yearnWrappingLibrary = new Interface(YearnWrappingAbi);
20 |
21 | return yearnWrappingLibrary.encodeFunctionData('unwrapYearnVaultToken', [
22 | params.vaultToken,
23 | params.sender,
24 | params.recipient,
25 | params.amount,
26 | params.outputReference,
27 | ]);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/services/pool/pool-weighted-compose.service.ts:
--------------------------------------------------------------------------------
1 | import { PoolCreationToken } from '~/modules/compose/ComposeProvider';
2 | import { PoolJoinContractCallData, PoolJoinData } from './pool-types';
3 | import { poolScaleTokenAmounts } from './lib/util';
4 | import { GqlPoolTokenBase, GqlToken } from '~/apollo/generated/graphql-codegen-generated';
5 | import { WeightedPoolEncoder } from '@balancer-labs/balancer-js';
6 |
7 | export class WeightedPoolComposeService {
8 | constructor() {}
9 |
10 | public joinGetContractCallData(tokenMetadata: GqlToken[], data: PoolJoinData): PoolJoinContractCallData {
11 | const assets = data.maxAmountsIn.map((token) => token.address);
12 | const maxAmountsIn = poolScaleTokenAmounts(data.maxAmountsIn, tokenMetadata);
13 | const userData = WeightedPoolEncoder.joinInit(maxAmountsIn);
14 |
15 | return {
16 | assets,
17 | maxAmountsIn,
18 | userData,
19 | type: 'JoinPool',
20 | };
21 | }
22 | }
23 |
24 | export const weightedPoolComposeService = new WeightedPoolComposeService();
25 |
--------------------------------------------------------------------------------
/lib/services/rpc-provider/static-json-rpc-batch-provier.ts:
--------------------------------------------------------------------------------
1 | import { Logger } from '@ethersproject/logger';
2 | import { Network } from '@ethersproject/networks';
3 | import { defineReadOnly } from '@ethersproject/properties';
4 | import { logger, providers } from 'ethers';
5 |
6 | export class StaticJsonRpcBatchProvider extends providers.JsonRpcBatchProvider {
7 | async detectNetwork(): Promise {
8 | let network = this.network;
9 | if (network == null) {
10 | network = await super.detectNetwork();
11 |
12 | if (!network) {
13 | logger.throwError('no network detected', Logger.errors.UNKNOWN_ERROR, {});
14 | }
15 |
16 | // If still not set, set it
17 | if (this._network == null) {
18 | // A static network does not support "any"
19 | defineReadOnly(this, '_network', network);
20 |
21 | this.emit('network', network, null);
22 | }
23 | }
24 | return network;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/services/staking/fresh-beets.service.ts:
--------------------------------------------------------------------------------
1 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
2 | import { BaseProvider } from '@ethersproject/providers';
3 | import { masterChefService, MasterChefService } from '~/lib/services/staking/master-chef.service';
4 | import { oldBnumScaleAmount, oldBnumToHumanReadable } from '~/lib/services/pool/lib/old-big-number';
5 |
6 | interface GetUserStakedBalanceInput {
7 | userAddress: string;
8 | farmId: string;
9 | provider: BaseProvider;
10 | fBeetsRatio: string;
11 | }
12 |
13 | export class FreshBeetsService {
14 | constructor(private readonly masterChefService: MasterChefService) {}
15 |
16 | public async getUserStakedBalance({
17 | userAddress,
18 | farmId,
19 | provider,
20 | fBeetsRatio,
21 | }: GetUserStakedBalanceInput): Promise {
22 | const stakedFbeets = await this.masterChefService.getUserStakedBalance({ provider, farmId, userAddress });
23 |
24 | return oldBnumToHumanReadable(oldBnumScaleAmount(stakedFbeets).times(fBeetsRatio));
25 | }
26 | }
27 |
28 | export const freshBeetsService = new FreshBeetsService(masterChefService);
29 |
--------------------------------------------------------------------------------
/lib/services/staking/staking-types.ts:
--------------------------------------------------------------------------------
1 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
2 |
3 | export interface StakingPendingRewardAmount {
4 | id: string;
5 | address: string;
6 | amount: AmountHumanReadable;
7 | }
8 |
9 | export interface ReliquaryStakingPendingRewardAmount extends StakingPendingRewardAmount {
10 | relicId: string;
11 | }
12 |
--------------------------------------------------------------------------------
/lib/services/token/token-types.ts:
--------------------------------------------------------------------------------
1 | import { BigNumber } from 'ethers';
2 |
3 | export interface TokenAmountHumanReadable {
4 | address: string;
5 | amount: string;
6 | }
7 |
8 | export interface TokenAmountScaled {
9 | address: string;
10 | amount: BigNumber;
11 | }
12 |
13 | export interface TokenBase {
14 | address: string;
15 | name: string;
16 | symbol: string;
17 | decimals: number;
18 | }
19 |
20 | export interface TokenBaseWithAmount extends TokenBase {
21 | amount: string;
22 | }
23 |
24 | export type AmountHumanReadable = string;
25 | export type AmountScaled = BigNumber;
26 | export type AmountScaledString = string;
27 |
28 | export type BalanceMap = Map;
29 |
30 | export interface AmountHumanReadableMap {
31 | [address: string]: AmountHumanReadable;
32 | }
33 |
--------------------------------------------------------------------------------
/lib/services/util/gas-price.service.ts:
--------------------------------------------------------------------------------
1 | export type GasPrice = {
2 | price: number;
3 | maxPriorityFeePerGas?: number;
4 | maxFeePerGas?: number;
5 | };
6 |
7 | export type GasPriceEstimation = {
8 | pricePerGwei: number;
9 | standardPriceGwei: number;
10 | fastPriceGwei: number;
11 | rapidPriceGwei: number;
12 | };
13 |
14 | export class GasPriceService {
15 | public async getLatest(): Promise {
16 | return null;
17 | }
18 |
19 | public async getGasPriceEstimation(): Promise {
20 | return null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/services/util/snapshot.service.ts:
--------------------------------------------------------------------------------
1 | import { Contract } from '@ethersproject/contracts';
2 | import { networkConfig } from '~/lib/config/network-config';
3 | import { BaseProvider } from '@ethersproject/providers';
4 | import DelegateRegistryAbi from '~/lib/abi/DelegateRegistry.json';
5 | import { Address } from 'wagmi';
6 |
7 | export class SnapshotService {
8 | constructor(private readonly contractAddress: string) {}
9 |
10 | public async getDelegation({
11 | userAddress,
12 | provider,
13 | id,
14 | }: {
15 | userAddress: Address | undefined;
16 | provider: BaseProvider;
17 | id: string;
18 | }): Promise {
19 | const contract = new Contract(this.contractAddress, DelegateRegistryAbi, provider);
20 | const address = await contract.delegation(userAddress, id);
21 | return address;
22 | }
23 | }
24 |
25 | export const snapshotService = new SnapshotService(networkConfig.snapshot.contractAddress);
26 |
--------------------------------------------------------------------------------
/lib/user/useUserAccount.ts:
--------------------------------------------------------------------------------
1 | import { useAccount } from 'wagmi';
2 | import { useEffect } from 'react';
3 | import { useBoolean } from '@chakra-ui/hooks';
4 | import { makeVar } from '@apollo/client';
5 |
6 | export const userAddressVar = makeVar(undefined);
7 |
8 | export function useUserAccount() {
9 | const query = useAccount();
10 | const [isFirstRender, setFirstRender] = useBoolean(true);
11 |
12 | useEffect(() => {
13 | setFirstRender.off();
14 | }, []);
15 |
16 | useEffect(() => {
17 | if (query.address !== userAddressVar()) {
18 | userAddressVar(query.address);
19 | }
20 | }, [query.address]);
21 |
22 | return {
23 | ...query,
24 | isLoading: query.isConnecting || isFirstRender,
25 | isConnecting: query.isConnecting || isFirstRender,
26 | userAddress: query.address?.toLowerCase(),
27 | isConnected: !!query.address && !isFirstRender,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/lib/user/useUserTokenBalances.tsx:
--------------------------------------------------------------------------------
1 | import { useGetTokens } from '~/lib/global/useToken';
2 | import { useUserBalances } from '~/lib/user/useUserBalances';
3 | import { createContext, ReactNode, useContext } from 'react';
4 |
5 | export const UserTokenBalancesContext = createContext | null>(null);
6 |
7 | export function UserTokenBalancesProvider(props: { children: ReactNode }) {
8 | const { tokens } = useGetTokens();
9 | const tokenAddresses = tokens.map((token) => token.address);
10 |
11 | const balances = useUserBalances(tokenAddresses);
12 |
13 | return {props.children};
14 | }
15 |
16 | export const useUserTokenBalances = () => useContext(UserTokenBalancesContext) as ReturnType;
17 |
--------------------------------------------------------------------------------
/lib/util/address.ts:
--------------------------------------------------------------------------------
1 | import { getAddress } from 'ethers/lib/utils';
2 | import { networkConfig } from '~/lib/config/network-config';
3 |
4 | export function addressesMatch(address1: string, address2: string) {
5 | return address1.toLowerCase() === address2.toLowerCase();
6 | }
7 |
8 | export function addressShortDisplayName(address: string) {
9 | const formatted = getAddress(address);
10 |
11 | return `${formatted.slice(0, 4)}...${formatted.slice(-4)}`;
12 | }
13 |
14 | export function isVault(address: string) {
15 | return addressesMatch(address, networkConfig.balancer.vault);
16 | }
17 |
18 | export function isBatchRelayer(address: string) {
19 | return addressesMatch(address, networkConfig.balancer.batchRelayer);
20 | }
21 |
--------------------------------------------------------------------------------
/lib/util/apr-util.ts:
--------------------------------------------------------------------------------
1 | import numeral from 'numeral';
2 | import { GqlPoolAprValue } from '~/apollo/generated/graphql-codegen-generated';
3 |
4 | const formatApr = (apr: string) => {
5 | if (parseFloat(apr) < 0.0000001) {
6 | return '0.00%';
7 | }
8 |
9 | return numeral(apr).format('0.00%');
10 | };
11 |
12 | export function getApr(apr: GqlPoolAprValue): string {
13 | if (apr.__typename === 'GqlPoolAprRange') {
14 | return `${formatApr(apr.min)} - ${formatApr(apr.max)}`;
15 | } else {
16 | return formatApr(apr.total);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lib/util/etherscan.ts:
--------------------------------------------------------------------------------
1 | import { networkConfig } from '~/lib/config/network-config';
2 |
3 | export function etherscanGetTokenUrl(tokenAddress: string): string {
4 | return `${networkConfig.etherscanUrl}/token/${tokenAddress}`;
5 | }
6 |
7 | export function etherscanGetAddressUrl(address: string): string {
8 | return `${networkConfig.etherscanUrl}/address/${address}`;
9 | }
10 |
11 | export function etherscanGetTxUrl(tx: string): string {
12 | return `${networkConfig.etherscanUrl}/tx/${tx}`;
13 | }
14 |
15 | export function etherscanGetBlockUrl(blockNumber: number): string {
16 | return `${networkConfig.etherscanUrl}/block/${blockNumber}`;
17 | }
18 |
19 | export function etherscanTxShortenForDisplay(txHash: string) {
20 | return txHash.slice(0, 12) + '...';
21 | }
22 |
23 | export function etherscanGetContractWriteUrl(address: string): string {
24 | return `${networkConfig.etherscanUrl}/address/${address}#writeContract`;
25 | }
26 |
27 | export function etherscanGetContractReadUrl(address: string): string {
28 | return `${networkConfig.etherscanUrl}/address/${address}#readContract`;
29 | }
30 |
--------------------------------------------------------------------------------
/lib/util/input-util.ts:
--------------------------------------------------------------------------------
1 | import { KeyboardEvent } from 'react';
2 |
3 | export function tokenInputBlockInvalidCharacters(event: KeyboardEvent): void {
4 | ['e', 'E', '+', '-'].includes(event.key) && event.preventDefault();
5 | }
6 |
7 | export function tokenInputTruncateDecimalPlaces(value: string, decimalPlaces: number): string {
8 | if (value.includes('.')) {
9 | const [leftDigits, rightDigits] = value.split('.');
10 |
11 | if (rightDigits && rightDigits.length > decimalPlaces) {
12 | const maxLength = leftDigits.length + decimalPlaces + 1;
13 |
14 | return value.slice(0, maxLength);
15 | }
16 | }
17 |
18 | return value;
19 | }
20 |
--------------------------------------------------------------------------------
/lib/util/transaction-util.ts:
--------------------------------------------------------------------------------
1 | export function transactionMessageFromError(error: Error): string {
2 | const unknown = error as any;
3 |
4 | if (unknown.reason) {
5 | const reason = unknown.reason as string;
6 |
7 | if (reason.indexOf('BAL#507') !== -1) {
8 | return 'Your transaction failed due to excessive slippage. You can increase your max slippage and try again. BAL#507';
9 | } else if (reason.indexOf('BAL#506') !== -1) {
10 | return 'Your transaction failed due to excessive slippage. You can increase your max slippage and try again. BAL#506';
11 | } else if (reason.indexOf('BAL#505') !== -1) {
12 | return 'Your transaction failed due to excessive slippage. You can increase your max slippage and try again. BAL#505';
13 | }
14 |
15 | return `An error occurred: ${reason}`;
16 | }
17 |
18 | if (error.message.indexOf('Connector not found') !== -1) {
19 | return 'Unable to connect to your wallet. Please ensure your wallet is unlocked and available.';
20 | }
21 |
22 | return `An error occurred: ${error.message}`;
23 | }
24 |
--------------------------------------------------------------------------------
/lib/util/urls.ts:
--------------------------------------------------------------------------------
1 | export function getBaseUrl() {
2 | if (typeof window === 'undefined') {
3 | return 'http://localhost:3000';
4 | }
5 |
6 | if (window.location.origin) {
7 | return window.location.origin;
8 | }
9 |
10 | const { protocol, hostname, port } = window.location;
11 | return `${protocol}//${hostname}${port ? ':' + port : ''}`;
12 | }
13 |
--------------------------------------------------------------------------------
/lib/util/useApproveBatchRelayer.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction, vaultContractConfig } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import { useUserAccount } from '~/lib/user/useUserAccount';
4 |
5 | export function useApproveBatchRelayer() {
6 | const networkConfig = useNetworkConfig();
7 | const { userAddress } = useUserAccount();
8 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
9 | config: {
10 | ...vaultContractConfig,
11 | functionName: 'setRelayerApproval',
12 | },
13 | transactionType: 'APPROVE',
14 | });
15 |
16 | function approve() {
17 | submit({
18 | args: [userAddress, networkConfig.balancer.batchRelayer, true],
19 | toastText: `Approve Batch Relayer`,
20 | });
21 | }
22 |
23 | return {
24 | approve,
25 | ...rest,
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/lib/util/useApproveMinter.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import BalancerPseudoMinterAbi from '~/lib/abi/BalancerPseudoMinter.json';
4 |
5 | export function useApproveMinter() {
6 | const networkConfig = useNetworkConfig();
7 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
8 | config: {
9 | addressOrName: networkConfig.gauge.balancerPseudoMinterAddress,
10 | contractInterface: BalancerPseudoMinterAbi,
11 | functionName: 'setMinterApproval',
12 | },
13 | transactionType: 'APPROVE',
14 | });
15 |
16 | function approve() {
17 | submit({
18 | args: [networkConfig.balancer.batchRelayer, true],
19 | toastText: `Approve batch relayer for minting`,
20 | });
21 | }
22 |
23 | return {
24 | approve,
25 | ...rest,
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/lib/util/useApproveToken.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import ERC20Abi from '../abi/ERC20.json';
3 | import { MaxUint256 } from '@ethersproject/constants';
4 | import { TokenBase } from '~/lib/services/token/token-types';
5 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
6 |
7 | export function useApproveToken(token: TokenBase) {
8 | const networkConfig = useNetworkConfig();
9 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
10 | config: {
11 | addressOrName: token.address || '',
12 | contractInterface: ERC20Abi,
13 | functionName: 'approve',
14 | },
15 | transactionType: 'APPROVE',
16 | });
17 |
18 | function approve(contractToApprove = networkConfig.balancer.vault) {
19 | submit({
20 | args: [contractToApprove, MaxUint256.toString()],
21 | toastText: `Approve ${token.symbol}`,
22 | });
23 | }
24 |
25 | return {
26 | approve,
27 | ...rest,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/lib/util/useHasBatchRelayerApproval.ts:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 | import { useUserAccount } from '~/lib/user/useUserAccount';
3 | import VaultAbi from '~/lib/abi/VaultAbi.json';
4 | import { useMultiCall } from '~/lib/util/useMultiCall';
5 |
6 | export function useHasBatchRelayerApproval() {
7 | const networkConfig = useNetworkConfig();
8 | const { userAddress } = useUserAccount();
9 |
10 | const { data, ...rest } = useMultiCall({
11 | abi: VaultAbi,
12 | enabled: !!userAddress,
13 | calls: [
14 | {
15 | address: networkConfig.balancer.vault,
16 | functionName: 'hasApprovedRelayer',
17 | args: [userAddress, networkConfig.balancer.batchRelayer],
18 | },
19 | ],
20 | });
21 |
22 | return {
23 | ...rest,
24 | data: (data ? data[0] : undefined) as boolean | undefined,
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/lib/util/useHasMinterApproval.ts:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 | import { useUserAccount } from '~/lib/user/useUserAccount';
3 | import { useMultiCall } from '~/lib/util/useMultiCall';
4 | import BalancerPseudoMinterAbi from '~/lib/abi/BalancerPseudoMinter.json';
5 |
6 | export function useHasMinterApproval() {
7 | const networkConfig = useNetworkConfig();
8 | const { userAddress } = useUserAccount();
9 |
10 | const { data, ...rest } = useMultiCall({
11 | abi: BalancerPseudoMinterAbi,
12 | enabled: !!userAddress && networkConfig.gaugeEnabled,
13 | calls: [
14 | {
15 | address: networkConfig.gauge.balancerPseudoMinterAddress,
16 | functionName: 'getMinterApproval',
17 | args: [networkConfig.balancer.batchRelayer, userAddress],
18 | },
19 | ],
20 | });
21 |
22 | return {
23 | ...rest,
24 | data: (data ? data[0] : undefined) as boolean | undefined,
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/lib/util/useUnwrapEth.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import WETHAbi from '../abi/WETH.json';
3 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
4 | import { parseUnits } from 'ethers/lib/utils';
5 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
6 |
7 | export function useUnwrapEth() {
8 | const networkConfig = useNetworkConfig();
9 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
10 | config: {
11 | addressOrName: networkConfig.wethAddress,
12 | contractInterface: WETHAbi,
13 | functionName: 'withdraw',
14 | },
15 | transactionType: 'UNWRAP',
16 | });
17 |
18 | function unwrap(amount: AmountHumanReadable) {
19 | submit({
20 | args: [parseUnits(amount, 18)],
21 | toastText: `Unwrapping ${amount} w${networkConfig.eth.symbol}`,
22 | });
23 | }
24 |
25 | return {
26 | unwrap,
27 | ...rest,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/lib/util/useUserAllowances.ts:
--------------------------------------------------------------------------------
1 | import { useAllowances } from '~/lib/util/useAllowances';
2 | import { TokenBase } from '~/lib/services/token/token-types';
3 | import { useUserAccount } from '~/lib/user/useUserAccount';
4 |
5 | export function useUserAllowances(tokens: (TokenBase | null)[], contractAddress?: string) {
6 | const { userAddress } = useUserAccount();
7 |
8 | return useAllowances(userAddress || null, tokens, contractAddress);
9 | }
10 |
--------------------------------------------------------------------------------
/lib/util/useWrapEth.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import WETHAbi from '../abi/WETH.json';
3 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
4 | import { parseUnits } from 'ethers/lib/utils';
5 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
6 |
7 | export function useWrapEth() {
8 | const networkConfig = useNetworkConfig();
9 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
10 | config: {
11 | addressOrName: networkConfig.wethAddress,
12 | contractInterface: WETHAbi,
13 | functionName: 'deposit',
14 | },
15 | transactionType: 'WRAP',
16 | });
17 |
18 | function wrap(amount: AmountHumanReadable) {
19 | submit({
20 | args: [],
21 | toastText: `Wrapping ${amount} ${networkConfig.eth.symbol}`,
22 | overrides: {
23 | value: parseUnits(amount, 18),
24 | },
25 | });
26 | }
27 |
28 | return {
29 | wrap,
30 | ...rest,
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/lib/util/web3.ts:
--------------------------------------------------------------------------------
1 | import { GqlToken } from '~/apollo/generated/graphql-codegen-generated';
2 |
3 | export async function addTokenToWallet(token: GqlToken | null) {
4 | const provider = window.ethereum as any;
5 | try {
6 | // wasAdded is a boolean. Like any RPC method, an error may be thrown.
7 | const wasAdded = await provider.request({
8 | method: 'wallet_watchAsset',
9 | params: {
10 | type: 'ERC20', // Initially only supports ERC20, but eventually more!
11 | options: {
12 | address: token?.address, // The address that the token is at.
13 | symbol: token?.symbol, // A ticker symbol or shorthand, up to 5 chars.
14 | decimals: token?.decimals, // The number of decimals in the token
15 | image: token?.logoURI, // A string url of the token logo
16 | },
17 | },
18 | });
19 | } catch (error) {
20 | console.log(error);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/wallet/useWalletConnectMetadata.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { useUserAccount } from '../user/useUserAccount';
3 |
4 | export function useWalletConnectMetadata() {
5 | const [walletName, setWalletName] = useState('');
6 | const { connector } = useUserAccount();
7 |
8 | useEffect(() => {
9 | if (!connector?.getProvider) return;
10 | if (connector.id !== 'walletConnect') return;
11 | connector.getProvider().then((provider) => {
12 | const walletConnectProvider = provider as any;
13 | try {
14 | setWalletName(walletConnectProvider.signer.session.peer.metadata.name);
15 | } catch {
16 | // Ignore errors in metadata
17 | }
18 | });
19 | }, [connector]);
20 |
21 | const isSafeAccountViaWalletConnect = walletName === 'Safe{Wallet}';
22 |
23 | return { isSafeAccountViaWalletConnect };
24 | }
25 |
--------------------------------------------------------------------------------
/modules/compose/AdvancedPoolComposeProgress.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 | import React from 'react';
3 | import { ChevronDown } from 'react-feather';
4 | import { useCompose } from './ComposeProvider';
5 |
6 | interface Props {
7 | step: number;
8 | }
9 |
10 | export default function AdvancedPoolComposeProgress({ step }: Props) {
11 | const { progressValidatedTo } = useCompose();
12 |
13 | const chevronColour = progressValidatedTo > step ? 'green.500' : 'red.500';
14 | return (
15 |
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/modules/compose/AdvancedPoolComposeSubmit.tsx:
--------------------------------------------------------------------------------
1 | import { Alert, Button, VStack } from '@chakra-ui/react';
2 | import React from 'react';
3 | import { useCompose } from './ComposeProvider';
4 | import { sumBy } from 'lodash';
5 | import { isAddress } from 'ethers/lib/utils.js';
6 |
7 | interface Props {}
8 |
9 | export function AdvancedPoolComposeSubmit(props: Props) {
10 | const { setActiveStep, tokens, feeManager, isPoolNameValid, getPoolFeeValidations, getTokenAndWeightValidations } =
11 | useCompose();
12 |
13 | const totalTokenWeight = sumBy(tokens, (token) => token.weight);
14 | const isInvalidTokenWeighTotal = totalTokenWeight < 100;
15 | const isInvalidFeeManager = feeManager === null || feeManager === '' || !isAddress(feeManager);
16 | const isPreviewDisabled =
17 | isInvalidTokenWeighTotal ||
18 | isInvalidFeeManager ||
19 | !getTokenAndWeightValidations().isValid ||
20 | !getPoolFeeValidations().isValid ||
21 | !isPoolNameValid();
22 | function goToPreview() {
23 | // TODO validate inputs
24 | setActiveStep('preview');
25 | }
26 |
27 | return (
28 |
29 |
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/modules/compose/ComposeFlow.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useCompose } from './ComposeProvider';
3 | import ComposeChooseFlowType from './ComposeChooseFlowType';
4 | import AdvancedPoolCreation from './AdvancedPoolCreation';
5 | import SimpleCreationChooseTokens from './SimpleCreationChooseTokens.tsx';
6 | import PoolComposePreview from './PoolComposePreview';
7 |
8 | interface Props {}
9 |
10 | export default function ComposeFlow(props: Props) {
11 | const { activeStep, creationExperience } = useCompose();
12 | switch (creationExperience) {
13 | case 'simple':
14 | switch (activeStep) {
15 | case 'choose-tokens':
16 | return ;
17 | default:
18 | return ;
19 | }
20 | case 'advanced':
21 | switch (activeStep) {
22 | case 'preview':
23 | return ;
24 | default:
25 | return ;
26 | }
27 | default:
28 | return ;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/modules/compose/SimpleCreationChooseTokens.tsx.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Heading, Text, VStack } from '@chakra-ui/react';
2 | import React from 'react';
3 | import Card from '~/components/card/Card';
4 |
5 | interface Props {}
6 |
7 | export default function SimpleCreationChooseTokens(props: Props) {
8 | return (
9 |
10 |
11 | fds
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/modules/global/GlobalRenderer.tsx:
--------------------------------------------------------------------------------
1 | import { useUserAccount } from '~/lib/user/useUserAccount';
2 | import { useGetAppGlobalPollingDataQuery, useGetUserDataQuery } from '~/apollo/generated/graphql-codegen-generated';
3 | import { useEffectOnce } from '~/lib/util/custom-hooks';
4 | import { useEffect, useRef } from 'react';
5 | import { Box } from '@chakra-ui/react';
6 |
7 | export function GlobalRenderer() {
8 | const currentUserAddress = useRef('');
9 | const { isConnected, userAddress } = useUserAccount();
10 | const { startPolling: startPollingAppData } = useGetAppGlobalPollingDataQuery({ fetchPolicy: 'network-only' });
11 | const { startPolling: startPollingUserData, refetch: refetchUserData } = useGetUserDataQuery({
12 | fetchPolicy: 'network-only',
13 | });
14 |
15 | useEffectOnce(() => {
16 | startPollingAppData(60_000);
17 | });
18 |
19 | useEffect(() => {
20 | if (userAddress) {
21 | startPollingUserData(30_000);
22 | }
23 |
24 | if (userAddress && userAddress !== currentUserAddress.current) {
25 | refetchUserData();
26 | currentUserAddress.current = userAddress;
27 | }
28 | }, [isConnected, userAddress]);
29 |
30 | return {null};
31 | }
32 |
--------------------------------------------------------------------------------
/modules/migrate/BeetsMigrationButton.tsx:
--------------------------------------------------------------------------------
1 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
2 | import { BeetsSubmitTransactionButton } from '~/components/button/BeetsSubmitTransactionButton';
3 | import { useMigrateBeets } from './lib/useMigrateBeets';
4 |
5 | interface Props {
6 | amount: AmountHumanReadable;
7 | onConfirmed?: () => void;
8 | onPending?: () => void;
9 | onSubmitting?: () => void;
10 | onCanceled?: () => void;
11 | isDisabled?: boolean;
12 | size?: string;
13 | inline?: boolean;
14 | isLoading?: boolean;
15 | }
16 |
17 | export function BeetsMigrationButton({ amount, ...rest }: Props) {
18 | const { migrate, ...query } = useMigrateBeets();
19 |
20 | return (
21 | {
25 | migrate(amount);
26 | }}
27 | {...rest}
28 | >
29 | Migrate
30 |
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/modules/migrate/lib/useMigrateBeets.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import MultiBeetsMigrationAbi from '~/lib/abi/MultiBeetsMigration.json';
3 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
4 | import { parseUnits } from 'ethers/lib/utils.js';
5 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
6 |
7 | export function useMigrateBeets() {
8 | const networkConfig = useNetworkConfig();
9 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
10 | config: {
11 | addressOrName: networkConfig.beets.migration,
12 | contractInterface: MultiBeetsMigrationAbi,
13 | functionName: 'exchange',
14 | },
15 | transactionType: 'MIGRATE',
16 | });
17 |
18 | function migrate(amount: AmountHumanReadable) {
19 | submit({
20 | args: [parseUnits(amount, 18)],
21 | toastText: `Migrate ${amount} multiBEETS`,
22 | });
23 | }
24 |
25 | return {
26 | migrate,
27 | ...rest,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/modules/nav/FooterLink.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Link, LinkProps } from '@chakra-ui/react';
2 | import { ReactNode } from 'react';
3 | import { NextLink } from '~/components/link/NextLink';
4 |
5 | interface Props extends LinkProps {
6 | children: ReactNode | ReactNode[];
7 | linkType?: 'internal' | 'external';
8 | href: string;
9 | }
10 |
11 | export function FooterLink({ linkType = 'external', href, ...rest }: Props) {
12 | return (
13 |
14 | {linkType === 'internal' ? (
15 |
19 | {rest.children}
20 |
21 | ) : (
22 |
30 | )}
31 |
32 | );
33 | }
34 |
--------------------------------------------------------------------------------
/modules/nav/NavbarLink.tsx:
--------------------------------------------------------------------------------
1 | import { Box, BoxProps, Text } from '@chakra-ui/react';
2 | import Link from 'next/link';
3 |
4 | interface Props extends Omit {
5 | selected?: boolean;
6 | href: string;
7 | text: string;
8 | }
9 |
10 | export function NavbarLink({ href, selected, text, ...rest }: Props) {
11 | return (
12 |
13 |
14 |
20 | {text}
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/modules/nav/SubNavBarStat.tsx:
--------------------------------------------------------------------------------
1 | import { HStack, Skeleton, StackProps, Text } from '@chakra-ui/react';
2 |
3 | import numeral from 'numeral';
4 |
5 | interface Props extends StackProps {
6 | loading: boolean;
7 | value: string;
8 | label: string;
9 | }
10 |
11 | export function SubNavBarStat({ label, value, loading, ...rest }: Props) {
12 | return (
13 |
14 |
15 | {label}:
16 |
17 | {loading ? (
18 |
19 | ) : (
20 |
21 | {numeral(value).format('$0.00a')}
22 |
23 | )}
24 |
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/modules/nav/lib/useGaugeClaimGetContractCallData.ts:
--------------------------------------------------------------------------------
1 | import { useQuery } from 'react-query';
2 | import { gaugeService } from '~/lib/services/staking/gauge.service';
3 | import { Zero } from '@ethersproject/constants';
4 |
5 | export function useGaugeClaimGetContractCallData(
6 | hasPendingNonBALRewards: boolean,
7 | hasPendingBalRewards: boolean,
8 | gauges: string[],
9 | ) {
10 | return useQuery(
11 | ['claimGetContractCallData', gauges],
12 | () => {
13 | const contractCallData = gaugeService.getGaugeClaimRewardsContractCallData({
14 | hasPendingNonBALRewards,
15 | hasPendingBalRewards,
16 | gauges,
17 | outputReference: Zero,
18 | });
19 |
20 | return contractCallData;
21 | },
22 | {
23 | enabled: gauges && !!gauges.length && (hasPendingNonBALRewards || hasPendingBalRewards),
24 | staleTime: 0,
25 | cacheTime: 0,
26 | },
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/modules/nav/lib/useUserGaugeClaimAllPendingRewards.ts:
--------------------------------------------------------------------------------
1 | import { batchRelayerContractConfig, useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 |
3 | export function useUserGaugeClaimAllPendingRewards() {
4 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
5 | config: batchRelayerContractConfig,
6 | transactionType: 'HARVEST',
7 | });
8 |
9 | function claimAll(contractCalls: string[]) {
10 | return submit({
11 | args: [contractCalls],
12 | toastText: 'Claim all pool rewards',
13 | });
14 | }
15 |
16 | return {
17 | claimAll,
18 | ...rest,
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/modules/nav/lib/useUserHarvestAllPendingRewards.ts:
--------------------------------------------------------------------------------
1 | import { useMasterChefHarvestAllRewards } from '~/lib/global/useMasterChefHarvestAllRewards';
2 |
3 | export function useUserHarvestAllPendingRewards() {
4 | const { harvestAll: masterChefHarvestAll, ...rest } = useMasterChefHarvestAllRewards();
5 |
6 | function harvestAll(farmIds: string[]) {
7 | if (farmIds.length === 1 && farmIds[0] === '') return;
8 | masterChefHarvestAll(farmIds);
9 | }
10 |
11 | return {
12 | ...rest,
13 | harvestAll,
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/PoolDetailActions.tsx:
--------------------------------------------------------------------------------
1 | import { BeetsBox } from '~/components/box/BeetsBox';
2 | import { BoxProps, Button, Flex } from '@chakra-ui/react';
3 |
4 | import NextLink from 'next/link';
5 | import { PoolDetailPossibleYieldText } from '~/modules/pool/detail/components/PoolDetailPossibleYieldText';
6 | import { usePool } from '~/modules/pool/lib/usePool';
7 |
8 | interface Props extends BoxProps {}
9 |
10 | export function PoolDetailActions({ ...rest }: Props) {
11 | const { pool, totalApr } = usePool();
12 |
13 | return (
14 |
15 | {totalApr > 0.05 ? : null}
16 | 0.05 ? 10 : 4}>
17 |
18 |
21 |
22 |
23 |
26 |
27 |
28 |
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/PoolHeaderStaking.tsx:
--------------------------------------------------------------------------------
1 | import { networkConfig } from '~/lib/config/network-config';
2 | import { PoolHeaderStakingAura } from './thirdparty/PoolHeaderStakingAura';
3 | import { PoolHeaderStakingFmoney } from './thirdparty/PoolHeaderStakingFmoney';
4 | import { PoolHeaderStakingMerkl } from './thirdparty/PoolHeaderStakingMerkl';
5 |
6 | export function PoolHeaderStaking({ poolId }: { poolId: string }) {
7 | const name = networkConfig.thirdPartyStakingPools.find((pool) => pool.poolId === poolId)?.name;
8 |
9 | switch (name) {
10 | case 'aura':
11 | return ;
12 | case 'merkl':
13 | return ;
14 | case 'fmoney':
15 | return ;
16 | default:
17 | return null;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/charts/chart-util.ts:
--------------------------------------------------------------------------------
1 | export function chartGetPrimaryColor(chainId: string, opacity: number) {
2 | if (chainId === '10') {
3 | return `rgba(119, 119, 119, ${opacity})`;
4 | }
5 |
6 | return `rgba(88, 95, 198, ${opacity})`;
7 | }
8 |
9 | export function chartGetSecondaryColor(chainId: string, opacity: number) {
10 | if (chainId === '10') {
11 | return `rgba(0, 255, 255, ${opacity})`;
12 | }
13 |
14 | return `rgba(143, 147, 214, ${opacity})`;
15 | }
16 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/thirdparty/PoolHeaderPoints.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from '@chakra-ui/react';
2 | import { CustomTooltip } from '~/components/tooltip/CustomTooltip';
3 |
4 | export function PoolHeaderPoints({ textString }: { textString: string }) {
5 | return (
6 |
9 | {textString}
10 |
11 | }
12 | content={'Liquidity providers in this pool also earn partner points'}
13 | border="2px"
14 | borderColor="beets.green"
15 | bg="whiteAlpha.300"
16 | />
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/thirdparty/PoolHeaderStakingAura.tsx:
--------------------------------------------------------------------------------
1 | import { Link, HStack, Text } from '@chakra-ui/react';
2 | import { CustomTooltip } from '~/components/tooltip/CustomTooltip';
3 | import { networkConfig } from '~/lib/config/network-config';
4 | import Image from 'next/image';
5 | import AuraLogo from '~/assets/logo/aura_iso_colors.png';
6 |
7 | export function PoolHeaderStakingAura({ poolId }: { poolId: string }) {
8 | const url = networkConfig.thirdPartyStakingPools.find((pool) => pool.poolId === poolId)?.url;
9 |
10 | return (
11 |
14 |
15 |
16 | Boosted rewards available on Aura
17 |
18 |
19 |
20 |
21 | }
22 | content={'For this pool you can deposit & stake your BPT on Aura Finance for extra boosted rewards'}
23 | border="2px"
24 | borderColor="aura.pink"
25 | _hover={{ borderColor: 'aura.purple' }}
26 | bg="whiteAlpha.300"
27 | />
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/thirdparty/PoolHeaderStakingFmoney.tsx:
--------------------------------------------------------------------------------
1 | import { Link, HStack, Text } from '@chakra-ui/react';
2 | import { CustomTooltip } from '~/components/tooltip/CustomTooltip';
3 | import { networkConfig } from '~/lib/config/network-config';
4 | import Image from 'next/image';
5 | import FmoneyLogo from '~/assets/logo/fmoney-pfp.png';
6 |
7 | export function PoolHeaderStakingFmoney({ poolId }: { poolId: string }) {
8 | const url = networkConfig.thirdPartyStakingPools.find((pool) => pool.poolId === poolId)?.url;
9 |
10 | return (
11 |
14 |
15 |
16 | Rewards available on fMoney Markets
17 |
18 |
19 |
20 |
21 | }
22 | content={'For this pool you can deposit & stake your BPT on fMoney Markets for rewards'}
23 | border="2px"
24 | borderColor="fmoney.green.100"
25 | _hover={{ borderColor: 'fmoney.green.400' }}
26 | bg="whiteAlpha.300"
27 | />
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/thirdparty/PoolHeaderStakingMerkl.tsx:
--------------------------------------------------------------------------------
1 | import { Link, HStack, Text } from '@chakra-ui/react';
2 | import { CustomTooltip } from '~/components/tooltip/CustomTooltip';
3 | import { networkConfig } from '~/lib/config/network-config';
4 | import Image from 'next/image';
5 | import MerklLogo from '~/assets/logo/merkl2x.png';
6 |
7 | export function PoolHeaderStakingMerkl({ poolId }: { poolId: string }) {
8 | const url = networkConfig.thirdPartyStakingPools.find((pool) => pool.poolId === poolId)?.url;
9 |
10 | return (
11 |
14 |
15 |
16 | Earn rewards on Merkl
17 |
18 |
19 |
20 |
21 | }
22 | content={'For this pool you can earn rewards on Merkl'}
23 | border="2px"
24 | borderColor="merkl.melrose"
25 | _hover={{ borderColor: 'white' }}
26 | bg="whiteAlpha.300"
27 | />
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/warning/PoolDetailWarning.tsx:
--------------------------------------------------------------------------------
1 | import { Box, HStack, Link } from '@chakra-ui/react';
2 | import { ToastType, useToast } from '~/components/toast/BeetsToast';
3 | import { useEffect } from 'react';
4 | import { PoolDetailWarning as PoolDetailWarningType } from '~/lib/config/network-config-type';
5 |
6 | interface Props {
7 | warning: PoolDetailWarningType;
8 | }
9 |
10 | export function PoolDetailWarning({ warning }: Props) {
11 | const { showToast } = useToast();
12 |
13 | useEffect(() => {
14 | showToast({
15 | id: 'pool-detail-alert',
16 | type: ToastType.Warn,
17 | content: (
18 |
19 |
20 | {warning.message}{' '}
21 | {warning.link && (
22 |
23 | {warning.link.text}
24 |
25 | )}
26 |
27 |
28 | ),
29 | });
30 | }, []);
31 |
32 | return null;
33 | }
34 |
--------------------------------------------------------------------------------
/modules/pool/detail/components/warning/PoolOvernightWarning.tsx:
--------------------------------------------------------------------------------
1 | import { Box, HStack, Link } from '@chakra-ui/react';
2 | import { usePool } from '~/modules/pool/lib/usePool';
3 | import { ToastType, useToast } from '~/components/toast/BeetsToast';
4 | import { useEffect } from 'react';
5 |
6 | export function PoolOvernightWarning() {
7 | const { showToast } = useToast();
8 | const { pool } = usePool();
9 |
10 | useEffect(() => {
11 | if (pool.id === '0xb1c9ac57594e9b1ec0f3787d9f6744ef4cb0a02400000000000000000000006e') {
12 | showToast({
13 | id: 'pool-detail-alert',
14 | type: ToastType.Info,
15 | content: (
16 |
17 |
18 | This pool is boosted by Overnight. When investing in this pool, the majority of your assets
19 | are wrapped in wUSD+ and wDAI+. Understand how Overnight generates yield prior to investing
20 | in this pool. Website:{' '}
21 |
22 | overnight.fi
23 |
24 |
25 |
26 | ),
27 | });
28 | }
29 | }, []);
30 |
31 | return null;
32 | }
33 |
--------------------------------------------------------------------------------
/modules/pool/invest/components/PoolInvestPreview.tsx:
--------------------------------------------------------------------------------
1 | import { Box, StackDivider, VStack } from '@chakra-ui/react';
2 | import { BeetsBox } from '~/components/box/BeetsBox';
3 | import { useInvest } from '~/modules/pool/invest/lib/useInvest';
4 | import { PoolInvestSummary } from '~/modules/pool/invest/components/PoolInvestSummary';
5 | import { PoolInvestActions } from '~/modules/pool/invest/components/PoolInvestActions';
6 | import TokenRow from '~/components/token/TokenRow';
7 | import React from 'react';
8 |
9 | interface Props {
10 | onInvestComplete(): void;
11 | onClose(): void;
12 | }
13 |
14 | export function PoolInvestPreview({ onInvestComplete, onClose }: Props) {
15 | const { selectedInvestTokensWithAmounts } = useInvest();
16 |
17 | return (
18 |
19 |
20 |
21 |
22 | } mt="4" p="2">
23 | {selectedInvestTokensWithAmounts.map((token) => {
24 | return ;
25 | })}
26 |
27 |
28 |
29 |
30 |
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/modules/pool/invest/components/PoolInvestPriceImpact.tsx:
--------------------------------------------------------------------------------
1 | import { HStack, Skeleton, Text, VStack } from '@chakra-ui/react';
2 | import React from 'react';
3 | import { usePoolJoinGetBptOutAndPriceImpactForTokensIn } from '~/modules/pool/invest/lib/usePoolJoinGetBptOutAndPriceImpactForTokensIn';
4 |
5 | export function PoolInvestPriceImpact() {
6 | const { formattedPriceImpact, hasHighPriceImpact, hasMediumPriceImpact, isLoading } =
7 | usePoolJoinGetBptOutAndPriceImpactForTokensIn();
8 |
9 | return (
10 |
11 |
12 |
13 | Price impact
14 |
15 | {isLoading ? (
16 |
17 | ) : (
18 |
22 | {formattedPriceImpact}
23 |
24 | )}
25 |
26 |
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/modules/pool/invest/components/PoolInvestStablePoolDescription.tsx:
--------------------------------------------------------------------------------
1 | import { Highlight } from '@chakra-ui/react';
2 |
3 | export function PoolInvestStablePoolDescription() {
4 | return (
5 | <>
6 |
7 | Stable pools allow you to invest with custom asset ratios without encountering significant price impact.
8 |
9 |
10 |
11 |
12 | Deposits that move the token balances closer to equal ratios will receive a small bonus, while deposits
13 | that move the ratios further apart will incur a small penalty.
14 |
15 |
16 |
17 |
18 |
19 | In instances where one asset in the pool loses its peg, it's possible to incur severe impermanent
20 | loss.
21 |
22 | >
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/modules/pool/invest/components/PoolInvestWeightedPoolDescription.tsx:
--------------------------------------------------------------------------------
1 | import { Highlight } from '@chakra-ui/react';
2 |
3 | export function PoolInvestWeightedPoolDescription() {
4 | return (
5 | <>
6 |
10 | Investing proportionally into this pool ensures you will not be subject to the fees associated with
11 | price impact.
12 |
13 |
14 |
15 |
19 | Alternatively, you can customize your investment and deposit in this pool with any tokens in your
20 | wallet. However, investing in this manner may shift the pool out of balance and is therefore subject to
21 | price impact.
22 |
23 |
24 |
25 | When investing in any liquidity pool, you will receive pool tokens (BPT) which represent your share of the
26 | pool.
27 | >
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/modules/pool/lib/usePoolGaugeClaimRewardsGetContractCallData.ts:
--------------------------------------------------------------------------------
1 | import { useQuery } from 'react-query';
2 | import { usePool } from '~/modules/pool/lib/usePool';
3 | import { gaugeService } from '~/lib/services/staking/gauge.service';
4 | import { usePoolUserPendingRewards } from './usePoolUserPendingRewards';
5 | import { Zero } from '@ethersproject/constants';
6 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
7 |
8 | export function usePoolGaugeClaimRewardsGetContractCallData() {
9 | const { pool } = usePool();
10 | const { hasPendingBalRewards, hasPendingNonBALRewards } = usePoolUserPendingRewards();
11 | const networkConfig = useNetworkConfig();
12 |
13 | const data = {
14 | hasPendingNonBALRewards,
15 | hasPendingBalRewards,
16 | outputReference: Zero,
17 | gauges: [pool.staking?.gauge?.id || ''],
18 | };
19 |
20 | return useQuery(
21 | ['unstakeGetContractCallData', data],
22 | () => {
23 | const contractCallData = gaugeService.getGaugeClaimRewardsContractCallData(data);
24 | return contractCallData;
25 | },
26 | { enabled: networkConfig.gaugeEnabled },
27 | );
28 | }
29 |
--------------------------------------------------------------------------------
/modules/pool/lib/usePoolWithOnChainData.tsx:
--------------------------------------------------------------------------------
1 | import { useQuery } from 'react-query';
2 | import { useProvider } from 'wagmi';
3 | import { GqlPoolUnion } from '~/apollo/generated/graphql-codegen-generated';
4 | import { useGetTokens } from '~/lib/global/useToken';
5 | import { poolOnChainBalanceService } from '~/lib/services/pool/pool-on-chain-balance.service';
6 |
7 | export function usePoolWithOnChainData(pool: GqlPoolUnion) {
8 | const provider = useProvider();
9 | const { priceFor } = useGetTokens();
10 |
11 | const tokenPrices = pool.tokens.map((token) => ({ address: token.address, price: priceFor(token.address) }));
12 |
13 | return useQuery(['usePoolWithOnChainData', pool.id, tokenPrices], async () => {
14 | return poolOnChainBalanceService.updatePoolWithOnChainBalanceData({ pool, provider, tokenPrices });
15 | });
16 | }
17 |
--------------------------------------------------------------------------------
/modules/pool/stake/lib/useGaugeCheckpoint.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import BeethovenCheckpointer from '~/lib/abi/BeethovenCheckpointer.json';
4 |
5 | export function useGaugeCheckpoint() {
6 | const networkConfig = useNetworkConfig();
7 |
8 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
9 | config: {
10 | addressOrName: networkConfig.gauge.checkpointHelper,
11 | contractInterface: BeethovenCheckpointer,
12 | functionName: 'checkpoint_my_gauges',
13 | },
14 | transactionType: 'CHECKPOINT',
15 | });
16 |
17 | function checkpoint(gauges: string[]) {
18 | return submit({
19 | args: [gauges],
20 | toastText: `Checkpoint my gauges`,
21 | walletText: `Checkpoint gauges to receive maximum boost`,
22 | });
23 | }
24 |
25 | return {
26 | checkpoint,
27 | ...rest,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/modules/pool/stake/lib/useGaugeStakingMigration.ts:
--------------------------------------------------------------------------------
1 | import { batchRelayerContractConfig, useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 |
3 | export function useStakingMigration() {
4 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
5 | config: batchRelayerContractConfig,
6 | transactionType: 'MIGRATE',
7 | });
8 |
9 | async function migrateGaugeStakedBalance(calls: string[]) {
10 | submit({
11 | args: [calls],
12 | toastText: 'Migrating staked balance...',
13 | walletText: 'Migrate staked balance.',
14 | });
15 | }
16 |
17 | return {
18 | migrateGaugeStakedBalance,
19 | ...rest,
20 | };
21 | }
--------------------------------------------------------------------------------
/modules/pool/stake/lib/usePoolUserStakingAllowance.ts:
--------------------------------------------------------------------------------
1 | import { useUserAllowances } from '~/lib/util/useUserAllowances';
2 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
3 | import { usePool } from '~/modules/pool/lib/usePool';
4 |
5 | export function usePoolUserStakingAllowance() {
6 | const { pool } = usePool();
7 |
8 | const { hasApprovalForAmount, ...rest } = useUserAllowances([pool], pool.staking?.address || '');
9 |
10 | function hasApprovalToStakeAmount(amount: AmountHumanReadable) {
11 | return hasApprovalForAmount(pool.address, amount);
12 | }
13 |
14 | return {
15 | ...rest,
16 | hasApprovalToStakeAmount,
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/modules/pool/withdraw/components/PoolWithdrawStablePoolDescription.tsx:
--------------------------------------------------------------------------------
1 | import { Highlight } from '@chakra-ui/react';
2 |
3 | export function PoolWithdrawStablePoolDescription() {
4 | return (
5 | <>
6 |
7 | Due to the unique design of stable pools, you can withdraw into a single token without encountering
8 | significant price impact.
9 |
10 |
11 |
12 |
13 | Withdraws that move the token balances closer to equal ratios will receive a small bonus, while
14 | withdraws that move the ratios further apart will incur a small penalty.
15 |
16 |
17 |
18 | When withdrawing from any liquidity pool, your BPT tokens are exchanged for the underlying pool assets.
19 | >
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/modules/pool/withdraw/components/PoolWithdrawWeightedPoolDescription.tsx:
--------------------------------------------------------------------------------
1 | import { Highlight } from '@chakra-ui/react';
2 |
3 | export function PoolWithdrawWeightedPoolDescription() {
4 | return (
5 | <>
6 |
10 | Withdrawing proportionally from this pool ensures you will not be subject to the potential fees caused
11 | by price impact.
12 |
13 |
14 |
15 |
16 | Alternatively, you can withdraw a single asset. This is similar to swapping all other assets for the
17 | selected asset, and is therefore subject to the fees associated with price impact.
18 |
19 |
20 |
21 | When withdrawing from any liquidity pool, your BPT tokens are exchanged for the underlying pool assets.
22 | >
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/modules/pool/withdraw/lib/usePoolExitGetProportionalWithdrawEstimate.ts:
--------------------------------------------------------------------------------
1 | import { useReactiveVar } from '@apollo/client';
2 | import { withdrawStateVar } from '~/modules/pool/withdraw/lib/useWithdrawState';
3 | import { useQuery } from 'react-query';
4 | import { oldBnumScaleAmount, oldBnumToHumanReadable } from '~/lib/services/pool/lib/old-big-number';
5 | import { usePoolUserBptBalance } from '~/modules/pool/lib/usePoolUserBptBalance';
6 | import { useWithdraw } from '~/modules/pool/withdraw/lib/useWithdraw';
7 | import { usePool } from '~/modules/pool/lib/usePool';
8 |
9 | export function usePoolExitGetProportionalWithdrawEstimate() {
10 | const { poolService, pool } = usePool();
11 | const { userWalletBptBalance } = usePoolUserBptBalance();
12 | const { proportionalPercent } = useReactiveVar(withdrawStateVar);
13 | const bptIn = oldBnumToHumanReadable(oldBnumScaleAmount(userWalletBptBalance).times(proportionalPercent / 100));
14 | const { selectedWithdrawTokenAddresses } = useWithdraw();
15 |
16 | return useQuery(
17 | ['exitGetProportionalWithdrawEstimate', pool.id, bptIn, selectedWithdrawTokenAddresses],
18 | async () => {
19 | const result = await poolService.exitGetProportionalWithdrawEstimate(bptIn, selectedWithdrawTokenAddresses);
20 |
21 | return result;
22 | },
23 | {},
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/modules/pool/withdraw/lib/usePoolExitGetSingleAssetWithdrawForBptIn.ts:
--------------------------------------------------------------------------------
1 | import { useReactiveVar } from '@apollo/client';
2 | import { withdrawStateVar } from '~/modules/pool/withdraw/lib/useWithdrawState';
3 | import { useQuery } from 'react-query';
4 | import { usePoolUserBptBalance } from '~/modules/pool/lib/usePoolUserBptBalance';
5 | import { usePool } from '~/modules/pool/lib/usePool';
6 |
7 | export function usePoolExitGetSingleAssetWithdrawForBptIn() {
8 | const { poolService } = usePool();
9 | const { singleAsset } = useReactiveVar(withdrawStateVar);
10 | const { userWalletBptBalance } = usePoolUserBptBalance();
11 |
12 | return useQuery(
13 | ['exitGetSingleAssetWithdrawForBptIn', userWalletBptBalance, singleAsset?.address],
14 | async () => {
15 | if (!singleAsset) {
16 | return {
17 | tokenAmount: '0',
18 | priceImpact: 0,
19 | };
20 | }
21 |
22 | return poolService.exitGetSingleAssetWithdrawForBptIn(userWalletBptBalance, singleAsset.address);
23 | },
24 | { enabled: !!singleAsset },
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/modules/pool/withdraw/lib/useWithdraw.ts:
--------------------------------------------------------------------------------
1 | import { GqlPoolToken } from '~/apollo/generated/graphql-codegen-generated';
2 | import { useWithdrawState } from '~/modules/pool/withdraw/lib/useWithdrawState';
3 | import { usePool } from '~/modules/pool/lib/usePool';
4 | import { sumBy } from 'lodash';
5 | import { useGetTokens } from '~/lib/global/useToken';
6 |
7 | export function useWithdraw() {
8 | const { pool } = usePool();
9 | const { selectedOptions, proportionalAmounts } = useWithdrawState();
10 |
11 | const selectedWithdrawTokens: GqlPoolToken[] = pool.withdrawConfig.options.map((option) =>
12 | selectedOptions[`${option.poolTokenIndex}`]
13 | ? option.tokenOptions.find(
14 | (tokenOption) => tokenOption.address === selectedOptions[`${option.poolTokenIndex}`],
15 | )!
16 | : option.tokenOptions[0],
17 | );
18 |
19 | const selectedWithdrawTokenAddresses = selectedWithdrawTokens.map((token) => token.address);
20 |
21 | return {
22 | selectedWithdrawTokens,
23 | selectedWithdrawTokenAddresses,
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/modules/pools/components/PoolListItemStaking.tsx:
--------------------------------------------------------------------------------
1 | import { networkConfig } from '~/lib/config/network-config';
2 | import { PoolListItemStakingAura } from './thirdparty/PoolListItemStakingAura';
3 | import { PoolListItemStakingFmoney } from './thirdparty/PoolListItemStakingFmoney';
4 | import { PoolListItemStakingMerkl } from './thirdparty/PoolListItemStakingMerkl';
5 |
6 | export function PoolListItemStaking({ poolId }: { poolId: string }) {
7 | const name = networkConfig.thirdPartyStakingPools.find((pool) => pool.poolId === poolId)?.name;
8 |
9 | switch (name) {
10 | case 'aura':
11 | return ;
12 | case 'merkl':
13 | return ;
14 | case 'fmoney':
15 | return ;
16 | default:
17 | return null;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/modules/pools/components/PoolListItemWarning.tsx:
--------------------------------------------------------------------------------
1 | import { AlertTriangle } from 'react-feather';
2 | import { Box, BoxProps } from '@chakra-ui/react';
3 | import BeetsTooltip from '~/components/tooltip/BeetsTooltip';
4 |
5 | interface Props extends BoxProps {
6 | message: string;
7 | }
8 |
9 | export function PoolListItemWarning({ message, ...rest }: Props) {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/modules/pools/components/PoolListSortLink.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, ButtonProps, Text, Button } from '@chakra-ui/react';
2 | import { ArrowUp, ArrowDown } from 'react-feather';
3 | import { GqlPoolOrderDirection } from '~/apollo/generated/graphql-codegen-generated';
4 |
5 | interface Props extends ButtonProps {
6 | title: string;
7 | orderDirection?: GqlPoolOrderDirection | null;
8 | }
9 |
10 | export default function PoolListSortLink({ title, orderDirection, ...rest }: Props) {
11 | return (
12 |
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/modules/pools/components/PoolListTop.tsx:
--------------------------------------------------------------------------------
1 | import { Box, HStack } from '@chakra-ui/react';
2 | import { PoolListTabs } from '~/modules/pools/components/PoolListTabs';
3 | import { PoolListSearch } from '~/modules/pools/components/PoolListSearch';
4 |
5 | export function PoolListTop() {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/modules/pools/components/thirdparty/PoolListItemPoints.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 | import BeetsTooltip from '~/components/tooltip/BeetsTooltip';
3 | import Image from 'next/image';
4 | import PointsIcon from '~/assets/icons/points.svg';
5 |
6 | export function PoolListItemPoints() {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/modules/pools/components/thirdparty/PoolListItemStakingAura.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 | import BeetsTooltip from '~/components/tooltip/BeetsTooltip';
3 | import Image from 'next/image';
4 | import AuraLogo from '~/assets/logo/aura_iso_colors.png';
5 |
6 | export function PoolListItemStakingAura() {
7 | return (
8 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/modules/pools/components/thirdparty/PoolListItemStakingFmoney.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 | import BeetsTooltip from '~/components/tooltip/BeetsTooltip';
3 | import Image from 'next/image';
4 | import FmoneyLogo from '~/assets/logo/fmoney-pfp.png';
5 |
6 | export function PoolListItemStakingFmoney() {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/modules/pools/components/thirdparty/PoolListItemStakingMerkl.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 | import BeetsTooltip from '~/components/tooltip/BeetsTooltip';
3 | import Image from 'next/image';
4 | import MerklLogo from '~/assets/logo/merkl2x.png';
5 |
6 | export function PoolListItemStakingMerkl() {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/modules/recovery-exit/lib/useGetRecoveryPoolTokens.ts:
--------------------------------------------------------------------------------
1 | import { useMultiCall } from '~/lib/util/useMultiCall';
2 | import VaultAbi from '../../../lib/abi/Vault.json';
3 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
4 | import { BigNumber } from 'ethers';
5 |
6 | export function useGetRecoveryPoolTokens(poolIds: string[]) {
7 | const networkConfig = useNetworkConfig();
8 |
9 | const multicall = useMultiCall<[string[], BigNumber[]]>({
10 | abi: VaultAbi,
11 | calls: poolIds.map((poolId) => ({
12 | address: networkConfig.balancer.vault,
13 | functionName: 'getPoolTokens',
14 | args: [poolId],
15 | })),
16 | enabled: poolIds.length > 0,
17 | });
18 |
19 | const poolTokens = multicall.data
20 | ? poolIds.map((poolId, index) => {
21 | const data = multicall.data[index];
22 |
23 | return {
24 | poolId,
25 | tokens: data ? data[0] : [],
26 | balances: data ? data[1] : [],
27 | };
28 | })
29 | : [];
30 |
31 | return {
32 | ...multicall,
33 | poolTokens,
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/modules/reliquary/components/RelicMaturityModal.tsx:
--------------------------------------------------------------------------------
1 | import { Modal, ModalCloseButton, ModalOverlay } from '@chakra-ui/react';
2 | import React from 'react';
3 | import { BeetsModalContent } from '~/components/modal/BeetsModal';
4 | import RelicMaturity from './charts/RelicMaturity';
5 |
6 | interface Props {
7 | isOpen: boolean;
8 | onClose: () => void;
9 | }
10 |
11 | export default function RelicMaturityModal({ isOpen, onClose }: Props) {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/modules/reliquary/components/ReliquaryBatchRelayerApprovalButton.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 | import { BeetsSubmitTransactionButton } from '~/components/button/BeetsSubmitTransactionButton';
3 | import { useBatchRelayerRelicApprove } from '../lib/useBatchRelayerRelicApprove';
4 |
5 | interface Props {
6 | contractToApprove?: string;
7 | onConfirmed?: () => void;
8 | onPending?: () => void;
9 | onSubmitting?: () => void;
10 | onCanceled?: () => void;
11 | isDisabled?: boolean;
12 | size?: string;
13 | buttonText?: string;
14 | }
15 |
16 | export function ReliquaryBatchRelayerApprovalButton({ buttonText, ...rest }: Props) {
17 | const { approveAll, approve, ...query } = useBatchRelayerRelicApprove(true);
18 |
19 | return (
20 |
21 | approveAll(true)}
25 | {...rest}
26 | borderColor="beets.green"
27 | _focus={{ boxShadow: 'none' }}
28 | submittingText="Confirm..."
29 | pendingText="Waiting..."
30 | >
31 | {buttonText ? buttonText : 'Approve Batch Relayer for all Relics'}
32 |
33 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/modules/reliquary/components/ReliquaryConnectWallet.tsx:
--------------------------------------------------------------------------------
1 | import { Heading, Text, VStack } from '@chakra-ui/react';
2 | import { motion } from 'framer-motion';
3 | import React from 'react';
4 | import { WalletConnectButton } from '~/components/button/WalletConnectButton';
5 |
6 | interface Props {}
7 |
8 | export default function ReliquaryConnectWallet(props: Props) {
9 | return (
10 |
21 |
22 | Get started by connecting your wallet
23 |
24 |
25 |
35 |
36 | );
37 | }
38 |
--------------------------------------------------------------------------------
/modules/reliquary/components/stats/ReliquaryGlobalStats.tsx:
--------------------------------------------------------------------------------
1 | import { Flex, Grid, GridItem } from '@chakra-ui/react';
2 | import React from 'react';
3 | import { ReliquaryCurveChart } from '../charts/ReliquaryCurveChart';
4 | import { ReliquaryDetailsCharts } from '../charts/ReliquaryDetailsCharts';
5 | import ReliquaryOverallStats from './ReliquaryOverallStats';
6 |
7 | export default function ReliquaryGlobalStats() {
8 | return (
9 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | );
35 | }
36 |
--------------------------------------------------------------------------------
/modules/reliquary/components/unused/ReliquaryCard.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Card from '~/components/card/Card';
3 |
4 | interface Props {
5 |
6 | }
7 |
8 | export default function ReliquaryCard(props: Props) {
9 |
10 | return (
11 |
12 | lmao
13 |
14 | )
15 | }
--------------------------------------------------------------------------------
/modules/reliquary/components/unused/ReliquaryMigrateDemoButton.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from '@chakra-ui/react';
2 | import { useReliquaryFbeetsMigrateContractCallData } from '~/modules/reliquary/lib/useReliquaryFbeetsMigrateContractCallData';
3 | import { useReliquaryZap } from '~/modules/reliquary/lib/useReliquaryZap';
4 |
5 | export function ReliquaryMigrateDemoButton() {
6 | // const { data: contractCalls, fbeetsBalance } = useReliquaryFbeetsMigrateContractCallData();
7 | // const { reliquaryZap } = useReliquaryZap('MIGRATE');
8 |
9 | // return (
10 | //
17 | // );
18 | return null;
19 | }
20 |
--------------------------------------------------------------------------------
/modules/reliquary/components/unused/ReliquaryMyStats.tsx:
--------------------------------------------------------------------------------
1 | import { Grid, GridItem } from '@chakra-ui/react';
2 | import React from 'react';
3 | import RelicMaturity from '../charts/RelicMaturity';
4 | import RelicApr from './RelicApr';
5 | import RelicLiquidity from './RelicLiquidity';
6 | import RelicRewards from './RelicRewards';
7 |
8 | export default function ReliquaryMyStats() {
9 | return (
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useAllRelicsWithdrawAndHarvestContractCallData.tsx:
--------------------------------------------------------------------------------
1 | import { useQuery } from 'react-query';
2 | import { useSlippage } from '~/lib/global/useSlippage';
3 | import { reliquaryZapService } from '~/lib/services/staking/reliquary-zap.service';
4 | import { useUserAccount } from '~/lib/user/useUserAccount';
5 | import { useAllRelicsDepositBalances } from './useAllRelicsDepositBalances';
6 |
7 | export function useAllRelicsWithdrawAndHarvestContractCallData() {
8 | const { userAddress } = useUserAccount();
9 | const { slippage } = useSlippage();
10 | const { relics, allRelicsBeetsAmount, allRelicsWftmAmount, alllRelicsBptTotal } = useAllRelicsDepositBalances();
11 |
12 | return useQuery(
13 | ['useAllRelicsWithdrawAndHarvestContractCallData', userAddress, slippage, relics.map((relic) => relic.relicId)],
14 | async () => {
15 | return reliquaryZapService.getReliquaryWithdrawManyAndHarvestContractCallData({
16 | userAddress: userAddress || '',
17 | relics,
18 | slippage,
19 | totalBptAmount: alllRelicsBptTotal,
20 | totalWftmAmount: allRelicsWftmAmount,
21 | totalBeetsAmount: allRelicsBeetsAmount,
22 | });
23 | },
24 | { enabled: !!userAddress },
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useBatchRelayerHasApprovedForAll.ts:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 | import { useMultiCall } from '~/lib/util/useMultiCall';
3 | import ReliquaryAbi from '~/lib/abi/Reliquary.json';
4 | import { useUserAccount } from '~/lib/user/useUserAccount';
5 |
6 | export function useBatchRelayerHasApprovedForAll() {
7 | const networkConfig = useNetworkConfig();
8 | const { userAddress } = useUserAccount();
9 |
10 | const { data, ...rest } = useMultiCall({
11 | abi: ReliquaryAbi,
12 | enabled: true,
13 | calls: [
14 | {
15 | address: networkConfig.reliquary.address,
16 | functionName: 'isApprovedForAll',
17 | args: [userAddress, networkConfig.balancer.batchRelayer],
18 | },
19 | ],
20 | });
21 |
22 | return {
23 | ...rest,
24 | data: (data ? data[0] : undefined) as boolean | undefined,
25 | };
26 | }
27 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useBatchRelayerHasRelicApproval.ts:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 | import { useMultiCall } from '~/lib/util/useMultiCall';
3 | import ReliquaryAbi from '~/lib/abi/Reliquary.json';
4 | import { isSameAddress } from '@balancer-labs/sdk';
5 |
6 | export function useBatchRelayerHasRelicApproval(relicId?: number) {
7 | const networkConfig = useNetworkConfig();
8 |
9 | const { data, ...rest } = useMultiCall({
10 | abi: ReliquaryAbi,
11 | enabled: typeof relicId === 'number',
12 | calls: [
13 | {
14 | address: networkConfig.reliquary.address,
15 | functionName: 'getApproved',
16 | args: [relicId],
17 | },
18 | ],
19 | });
20 |
21 | return {
22 | ...rest,
23 | data: (data ? isSameAddress(data[0] as string, networkConfig.balancer.batchRelayer) : undefined) as
24 | | boolean
25 | | undefined,
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useBatchRelayerRelicApprove.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import ReliquaryAbi from '~/lib/abi/Reliquary.json';
4 |
5 | export function useBatchRelayerRelicApprove(useApproveAll = false) {
6 | const networkConfig = useNetworkConfig();
7 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
8 | config: {
9 | addressOrName: networkConfig.reliquary.address,
10 | contractInterface: ReliquaryAbi,
11 | functionName: useApproveAll ? 'setApprovalForAll' : 'approve',
12 | },
13 | transactionType: 'APPROVE',
14 | });
15 |
16 | function approve(relicId: number) {
17 | submit({
18 | args: [networkConfig.balancer.batchRelayer, relicId],
19 | toastText: `Approve relic #${relicId}`,
20 | });
21 | }
22 |
23 | function approveAll(approve: boolean) {
24 | submit({
25 | args: [networkConfig.balancer.batchRelayer, approve],
26 | toastText: 'Approve all current and future relics',
27 | });
28 | }
29 |
30 | return {
31 | approve,
32 | approveAll,
33 | ...rest,
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useDelegateClear.tsx:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import DelegateRegistryAbi from '~/lib/abi/DelegateRegistry.json';
4 |
5 | export function useDelegateClear() {
6 | const networkConfig = useNetworkConfig();
7 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
8 | config: {
9 | addressOrName: networkConfig.snapshot.contractAddress,
10 | contractInterface: DelegateRegistryAbi,
11 | functionName: 'clearDelegate',
12 | },
13 | transactionType: 'UNDELEGATE',
14 | });
15 |
16 | function clearDelegate() {
17 | submit({
18 | args: [networkConfig.snapshot.id],
19 | toastText: 'Undelegate to MDs',
20 | });
21 | }
22 |
23 | return {
24 | clearDelegate,
25 | ...rest,
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useDelegateSet.tsx:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import DelegateRegistryAbi from '~/lib/abi/DelegateRegistry.json';
4 |
5 | export function useDelegateSet() {
6 | const networkConfig = useNetworkConfig();
7 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
8 | config: {
9 | addressOrName: networkConfig.snapshot.contractAddress,
10 | contractInterface: DelegateRegistryAbi,
11 | functionName: 'setDelegate',
12 | },
13 | transactionType: 'DELEGATE',
14 | });
15 |
16 | function setDelegate() {
17 | submit({
18 | args: [networkConfig.snapshot.id, networkConfig.snapshot.delegateAddress],
19 | toastText: 'Delegate to MDs',
20 | });
21 | }
22 |
23 | return {
24 | setDelegate,
25 | ...rest,
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useDelegation.tsx:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 | import { useQuery } from 'react-query';
3 | import { snapshotService } from '~/lib/services/util/snapshot.service';
4 | import { useUserAccount } from '~/lib/user/useUserAccount';
5 | import { Address, useProvider } from 'wagmi';
6 |
7 | export function useDelegation() {
8 | const { userAddress } = useUserAccount();
9 | const provider = useProvider();
10 | const networkConfig = useNetworkConfig();
11 |
12 | return useQuery(
13 | ['getDelegation', userAddress],
14 | async (): Promise => {
15 | const delegationAddress = await snapshotService.getDelegation({
16 | userAddress: userAddress as Address,
17 | provider,
18 | id: networkConfig.snapshot.id,
19 | });
20 | return delegationAddress === networkConfig.snapshot.delegateAddress;
21 | },
22 | { enabled: !!userAddress },
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useRelicBurn.tsx:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import ReliquaryAbi from '~/lib/abi/Reliquary.json';
4 |
5 | export function useRelicBurn() {
6 | const networkConfig = useNetworkConfig();
7 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
8 | config: {
9 | addressOrName: networkConfig.reliquary.address,
10 | contractInterface: ReliquaryAbi,
11 | functionName: 'burn',
12 | },
13 | transactionType: 'BURN',
14 | });
15 |
16 | function burn(relicId: string) {
17 | submit({
18 | args: [parseInt(relicId, 10)],
19 | toastText: `Burn relic #${relicId}`,
20 | });
21 | }
22 |
23 | return {
24 | burn,
25 | ...rest,
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useRelicHarvestRewards.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 | import ReliquaryAbi from '~/lib/abi/Reliquary.json';
4 | import { useUserAccount } from '~/lib/user/useUserAccount';
5 | import useReliquary from '~/modules/reliquary/lib/useReliquary';
6 |
7 | export function useRelicHarvestRewards() {
8 | const networkConfig = useNetworkConfig();
9 | const { userAddress } = useUserAccount();
10 | const { selectedRelicId } = useReliquary();
11 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
12 | config: {
13 | addressOrName: networkConfig.reliquary.address,
14 | contractInterface: ReliquaryAbi,
15 | functionName: 'harvest',
16 | },
17 | transactionType: 'HARVEST',
18 | });
19 |
20 | function harvest() {
21 | submit({
22 | args: [selectedRelicId, userAddress],
23 | toastText: `Harvesting rewards for relic #${selectedRelicId}`,
24 | walletText: `Harvest rewards for relic #${selectedRelicId}`,
25 | });
26 | }
27 |
28 | return {
29 | harvest,
30 | ...rest,
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useRelicPendingRewards.ts:
--------------------------------------------------------------------------------
1 | import { useQuery } from 'react-query';
2 | import useReliquary from '~/modules/reliquary/lib/useReliquary';
3 | import { reliquaryService } from '~/lib/services/staking/reliquary.service';
4 | import { useProvider } from 'wagmi';
5 |
6 | export function useRelicPendingRewards() {
7 | const { selectedRelic } = useReliquary();
8 | const provider = useProvider();
9 |
10 | return useQuery(
11 | ['relicPendingRewards', selectedRelic?.relicId],
12 | async () => {
13 | return reliquaryService.getPendingRewardsForRelic({
14 | relicId: selectedRelic?.relicId || '0',
15 | provider,
16 | });
17 | },
18 | { enabled: !!selectedRelic },
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryCurrentStep.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export interface CurrentStepContextType {
4 | updateCurrentStep: (id: string) => void;
5 | currentStep: string | null;
6 | }
7 |
8 | export const CurrentStepContext = React.createContext(null);
9 |
10 | export function _useCurrentStep() {
11 | const [currentStep, setCurrentStep] = React.useState(null);
12 |
13 | const updateCurrentStep = (id: string) => {
14 | setCurrentStep(id);
15 | };
16 |
17 | return {
18 | currentStep,
19 | updateCurrentStep,
20 | };
21 | }
22 |
23 | export function CurrentStepProvider(props: { children: React.ReactNode }) {
24 | const steps = _useCurrentStep();
25 | return {props.children};
26 | }
27 |
28 | export const useCurrentStep = () => React.useContext(CurrentStepContext) as ReturnType;
29 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryDepositImpact.ts:
--------------------------------------------------------------------------------
1 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
2 |
3 | import { useQuery } from 'react-query';
4 | import { ReliquaryService } from '~/lib/services/staking/reliquary.service';
5 | import { useRef } from 'react';
6 | import { useProvider } from 'wagmi';
7 |
8 | export function useReliquaryDepositImpact(amount: number, relicId?: string) {
9 | const networkConfig = useNetworkConfig();
10 | const provider = useProvider();
11 | const reliquaryService = useRef(
12 | new ReliquaryService(networkConfig.reliquary.address, networkConfig.chainId, networkConfig.beets.address),
13 | ).current;
14 | const depositImpactQuery = useQuery(
15 | 'relicDepositImpact',
16 | async () => {
17 | if (Number.isNaN(amount) || !relicId) {
18 | return;
19 | }
20 | return await reliquaryService.getDepositImpact({
21 | relicId,
22 | provider,
23 | amount,
24 | });
25 | },
26 | {
27 | enabled: !!relicId && !Number.isNaN(amount),
28 | },
29 | );
30 |
31 | return depositImpactQuery;
32 | }
33 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryGlobalStats.ts:
--------------------------------------------------------------------------------
1 | import { useGetReliquaryFarmSnapshotsQuery } from '~/apollo/generated/graphql-codegen-generated';
2 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
3 |
4 | export function useReliquaryGlobalStats() {
5 | const config = useNetworkConfig();
6 | const { data, ...rest } = useGetReliquaryFarmSnapshotsQuery({
7 | variables: { id: `${config.reliquary.fbeets.farmId}`, range: 'THIRTY_DAYS' },
8 | });
9 |
10 | const latest = data && data.snapshots.length > 0 ? data.snapshots[data.snapshots.length - 1] : null;
11 |
12 | return {
13 | ...rest,
14 | data: latest,
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryHarvestAllContractCallData.ts:
--------------------------------------------------------------------------------
1 | import { useQuery } from 'react-query';
2 | import { reliquaryZapService } from '~/lib/services/staking/reliquary-zap.service';
3 | import { useUserAccount } from '~/lib/user/useUserAccount';
4 |
5 | export function useReliquaryHarvestAllContractCallData(relicIds: number[]) {
6 | const { userAddress } = useUserAccount();
7 |
8 | return useQuery(
9 | ['reliquaryHarvestAllContractCallData', relicIds, userAddress],
10 | async () => {
11 | return reliquaryZapService.getReliquaryHarvestAllContractCallData({
12 | relicIds,
13 | recipient: userAddress || '',
14 | });
15 | },
16 | { enabled: !!userAddress && relicIds.length !== 0 },
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryHarvestAllRewards.ts:
--------------------------------------------------------------------------------
1 | import { batchRelayerContractConfig, useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 |
3 | export function useReliquaryHarvestAllRewards() {
4 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
5 | config: batchRelayerContractConfig,
6 | transactionType: 'HARVEST',
7 | });
8 |
9 | function harvestAll(calls: string[]) {
10 | submit({
11 | args: [calls],
12 | toastText: 'Harvesting all pending relic rewards',
13 | walletText: 'Harvest all pending relic rewards',
14 | });
15 | }
16 |
17 | return {
18 | harvestAll,
19 | ...rest,
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryLevelUp.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import { MaxUint256 } from '@ethersproject/constants';
3 | import { TokenBase } from '~/lib/services/token/token-types';
4 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
5 | import ReliquaryAbi from '~/lib/abi/Reliquary.json';
6 |
7 | export function useReliquaryLevelUp() {
8 | const networkConfig = useNetworkConfig();
9 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
10 | config: {
11 | addressOrName: networkConfig.reliquary.address,
12 | contractInterface: ReliquaryAbi,
13 | functionName: 'updatePosition',
14 | },
15 | transactionType: 'LEVEL_UP',
16 | });
17 |
18 | function levelUp(relicId: string) {
19 | submit({
20 | args: [parseInt(relicId, 10)],
21 | toastText: `Level Up relic #${relicId}`,
22 | });
23 | }
24 |
25 | return {
26 | levelUp,
27 | ...rest,
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryPendingRewards.ts:
--------------------------------------------------------------------------------
1 | import { useQuery } from 'react-query';
2 | import { reliquaryService } from '~/lib/services/staking/reliquary.service';
3 | import { useProvider } from 'wagmi';
4 | import { useUserAccount } from '~/lib/user/useUserAccount';
5 | import { networkConfig } from '~/lib/config/network-config';
6 |
7 | export function useReliquaryPendingRewards() {
8 | const provider = useProvider();
9 | const { userAddress } = useUserAccount();
10 |
11 | return useQuery(
12 | ['reliquaryPendingRewards', networkConfig.reliquary.fbeets.farmId, userAddress],
13 | async () => {
14 | return reliquaryService.getPendingRewards({
15 | farmIds: [networkConfig.reliquary.fbeets.farmId.toString()],
16 | userAddress: userAddress || '',
17 | provider,
18 | });
19 | },
20 | { enabled: !!userAddress && !!networkConfig.fbeets.address },
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/modules/reliquary/lib/useReliquaryZap.ts:
--------------------------------------------------------------------------------
1 | import { batchRelayerContractConfig, useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 |
3 | export function useReliquaryZap(type: 'MIGRATE' | 'DEPOSIT' | 'WITHDRAW') {
4 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
5 | config: batchRelayerContractConfig,
6 | transactionType: type === 'WITHDRAW' ? 'EXIT' : 'JOIN',
7 | });
8 |
9 | async function reliquaryZap(calls: string[]) {
10 | submit({
11 | args: [calls],
12 | toastText:
13 | type === 'WITHDRAW'
14 | ? 'Withdrawing from maBEETS'
15 | : type === 'MIGRATE'
16 | ? 'Migrating into maBEETS'
17 | : 'Depositing into maBEETS',
18 | walletText:
19 | type === 'WITHDRAW'
20 | ? 'Withdraw from maBEETS'
21 | : type === 'MIGRATE'
22 | ? 'Migrate into maBEETS'
23 | : 'Deposit into maBEETS',
24 | });
25 | }
26 |
27 | return {
28 | reliquaryZap,
29 | ...rest,
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/modules/reliquary/migrate/components/ReliquarySonicMigrateBridgeFtm.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Heading, Text, Link, Flex } from '@chakra-ui/react';
2 | import { ExternalLink } from 'react-feather';
3 |
4 | export function ReliquarySonicMigrateBridgeFtm() {
5 | return (
6 |
7 | 4. Upgrade your FTM to S
8 | Use the Sonic native bridge to upgrade your FTM to S:
9 |
10 |
11 | https://my.soniclabs.com/upgrade
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/modules/reliquary/migrate/components/ReliquarySonicMigrateNextSteps.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Heading, Text, Link, Flex } from '@chakra-ui/react';
2 | import { ExternalLink } from 'react-feather';
3 |
4 | export function ReliquarySonicMigrateNextSteps() {
5 | return (
6 |
7 | 6. Next steps
8 | Once you've completed the steps above, you can create your maBEETS relic on Sonic.
9 |
10 |
11 | https://ma.beets.fi/
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/modules/reliquary/migrate/components/ReliquarySonicMigrateStakeS.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Heading, Text, Link, Flex } from '@chakra-ui/react';
2 | import { ExternalLink } from 'react-feather';
3 |
4 | export function ReliquarySonicMigrateStakeS() {
5 | return (
6 |
7 | 5. Stake S for stS
8 | Stake your S to receive stS, Sonic's liquid staking token.
9 |
10 |
11 | https://beets.fi/stake
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/modules/reliquary/reliquary.gql:
--------------------------------------------------------------------------------
1 | query GetReliquaryFarmSnapshots($id: String!, $range: GqlPoolSnapshotDataRange!) {
2 | snapshots: beetsPoolGetReliquaryFarmSnapshots(id: $id, range: $range) {
3 | id
4 | farmId
5 | timestamp
6 | totalBalance
7 | totalLiquidity
8 | levelBalances {
9 | id
10 | level
11 | balance
12 | }
13 | relicCount
14 | totalBalance
15 | userCount
16 | tokenBalances {
17 | id
18 | address
19 | balance
20 | symbol
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/modules/reliquary/withdraw/components/ReliquaryWithdrawDescription.tsx:
--------------------------------------------------------------------------------
1 | import { Highlight } from '@chakra-ui/react';
2 |
3 | export function ReliquaryWithdrawDescription() {
4 | return (
5 | <>
6 |
10 | Withdrawing proportionally from this relic ensures you will not be subject to the potential fees caused
11 | by price impact.
12 |
13 |
14 |
15 |
16 | For now withdrawing a single asset is not available. This will be implemented at a later date.
17 |
18 |
19 |
20 | When withdrawing from any relic, your fBEETS are exchanged for the underlying tokens.
21 | >
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/modules/reliquary/withdraw/lib/useReliquaryExitGetProportionalWithdrawEstimate.ts:
--------------------------------------------------------------------------------
1 | import { useReactiveVar } from '@apollo/client';
2 | import { withdrawStateVar } from '~/modules/reliquary/withdraw/lib/useReliquaryWithdrawState';
3 | import { useQuery } from 'react-query';
4 | import { oldBnumScaleAmount, oldBnumToHumanReadable } from '~/lib/services/pool/lib/old-big-number';
5 | import { useReliquaryWithdraw } from '~/modules/reliquary/withdraw/lib/useReliquaryWithdraw';
6 | import { usePool } from '~/modules/pool/lib/usePool';
7 | import useReliquary from '~/modules/reliquary/lib/useReliquary';
8 |
9 | export function useReliquaryExitGetProportionalWithdrawEstimate() {
10 | const { poolService, pool } = usePool();
11 | const { proportionalPercent } = useReactiveVar(withdrawStateVar);
12 | const { selectedRelic } = useReliquary();
13 | const bptIn = oldBnumToHumanReadable(
14 | oldBnumScaleAmount(selectedRelic?.amount || '').times(proportionalPercent / 100),
15 | );
16 | const { selectedWithdrawTokenAddresses } = useReliquaryWithdraw();
17 |
18 | return useQuery(
19 | ['exitGetProportionalWithdrawEstimate', pool.id, bptIn, selectedWithdrawTokenAddresses],
20 | async () => {
21 | const result = await poolService.exitGetProportionalWithdrawEstimate(bptIn, selectedWithdrawTokenAddresses);
22 |
23 | return result;
24 | },
25 | {},
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/modules/reliquary/withdraw/lib/useReliquaryExitGetSingleAssetWithdrawForBptIn.ts:
--------------------------------------------------------------------------------
1 | import { useReactiveVar } from '@apollo/client';
2 | import { withdrawStateVar } from '~/modules/reliquary/withdraw/lib/useReliquaryWithdrawState';
3 | import { useQuery } from 'react-query';
4 | import { usePoolUserBptBalance } from '~/modules/pool/lib/usePoolUserBptBalance';
5 | import { usePool } from '~/modules/pool/lib/usePool';
6 |
7 | export function useReliquaryExitGetSingleAssetWithdrawForBptIn() {
8 | const { poolService } = usePool();
9 | const { singleAsset } = useReactiveVar(withdrawStateVar);
10 | const { userWalletBptBalance } = usePoolUserBptBalance();
11 |
12 | return useQuery(
13 | ['exitGetSingleAssetWithdrawForBptIn', userWalletBptBalance, singleAsset?.address],
14 | async () => {
15 | if (!singleAsset) {
16 | return {
17 | tokenAmount: '0',
18 | priceImpact: 0,
19 | };
20 | }
21 |
22 | return poolService.exitGetSingleAssetWithdrawForBptIn(userWalletBptBalance, singleAsset.address);
23 | },
24 | { enabled: !!singleAsset },
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/modules/reliquary/withdraw/lib/useReliquaryWithdraw.ts:
--------------------------------------------------------------------------------
1 | import { GqlPoolToken } from '~/apollo/generated/graphql-codegen-generated';
2 | import { useReliquaryWithdrawState } from '~/modules/reliquary/withdraw/lib/useReliquaryWithdrawState';
3 | import { usePool } from '~/modules/pool/lib/usePool';
4 |
5 | export function useReliquaryWithdraw() {
6 | const { pool } = usePool();
7 | const { selectedOptions } = useReliquaryWithdrawState();
8 |
9 | const selectedWithdrawTokens: GqlPoolToken[] = pool.withdrawConfig.options.map((option) =>
10 | selectedOptions[`${option.poolTokenIndex}`]
11 | ? option.tokenOptions.find(
12 | (tokenOption) => tokenOption.address === selectedOptions[`${option.poolTokenIndex}`],
13 | )!
14 | : option.tokenOptions[0],
15 | );
16 |
17 | const selectedWithdrawTokenAddresses = selectedWithdrawTokens.map((token) => token.address);
18 |
19 | return {
20 | selectedWithdrawTokens,
21 | selectedWithdrawTokenAddresses,
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/modules/sftmx/components/stats/SftmxStatsFtmValidator.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@chakra-ui/react';
2 | import Card from '~/components/card/Card';
3 | import { useSftmxGetStakingData } from '../../lib/useSftmxGetStakingData';
4 | import { SftmxChartsFtmValidator } from '../charts/SftmxChartsFtmValidator';
5 | import { groupBy, sortBy, sumBy } from 'lodash';
6 |
7 | export function SftmxStatsFtmValidator() {
8 | const { data } = useSftmxGetStakingData();
9 | const validatorsGroupedAndSummed = groupBy(data?.sftmxGetStakingData.vaults, 'validatorId');
10 | const totalFtmAmounts = Object.keys(validatorsGroupedAndSummed).map((key) => ({
11 | name: key,
12 | value: sumBy(validatorsGroupedAndSummed[key].map((value) => parseFloat(value.ftmAmountStaked))),
13 | validatorAddress: validatorsGroupedAndSummed[key][0].validatorAddress.toLowerCase(),
14 | }));
15 |
16 | const totalFtmAmountsSorted = sortBy(totalFtmAmounts, 'value').reverse();
17 |
18 | return (
19 |
20 |
21 | {data && }
22 |
23 |
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/modules/sftmx/components/tabs/stake/SftmxStakeButton.tsx:
--------------------------------------------------------------------------------
1 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
2 | import { BeetsSubmitTransactionButton } from '~/components/button/BeetsSubmitTransactionButton';
3 | import { useSftmxStake } from '../../../lib/useSftmxStake';
4 |
5 | interface Props {
6 | amount: AmountHumanReadable;
7 | onConfirmed?: () => void;
8 | onPending?: () => void;
9 | onSubmitting?: () => void;
10 | onCanceled?: () => void;
11 | isDisabled?: boolean;
12 | size?: string;
13 | inline?: boolean;
14 | isLoading?: boolean;
15 | }
16 |
17 | export function SftmxStakeButton({ amount, ...rest }: Props) {
18 | const { stake, ...query } = useSftmxStake();
19 |
20 | return (
21 | {
25 | stake(amount);
26 | }}
27 | {...rest}
28 | >
29 | Stake
30 |
31 | );
32 | }
33 |
--------------------------------------------------------------------------------
/modules/sftmx/components/tabs/withdraw/SftmxWithdrawButton.tsx:
--------------------------------------------------------------------------------
1 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
2 | import { BeetsSubmitTransactionButton } from '~/components/button/BeetsSubmitTransactionButton';
3 | import { useSftmxWithdraw } from '../../../lib/useSftmxWithdraw';
4 |
5 | interface Props {
6 | amount: AmountHumanReadable;
7 | wrId: string;
8 | onConfirmed?: () => void;
9 | onPending?: () => void;
10 | onSubmitting?: () => void;
11 | onCanceled?: () => void;
12 | isDisabled?: boolean;
13 | size?: string;
14 | inline?: boolean;
15 | isLoading?: boolean;
16 | isWithdrawn: boolean;
17 | }
18 |
19 | export function SftmxWithdrawButton({ amount, wrId, isWithdrawn, ...rest }: Props) {
20 | const { withdraw, ...query } = useSftmxWithdraw();
21 |
22 | return (
23 | {
27 | withdraw(amount, wrId);
28 | }}
29 | {...rest}
30 | >
31 | {isWithdrawn ? 'Withdrawn' : 'Withdraw'}
32 |
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/modules/sftmx/components/tabs/withdraw/SftmxWithdrawalRequestsHeader.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from '@chakra-ui/layout';
2 | import { Grid, GridItem } from '@chakra-ui/react';
3 |
4 | export default function SftmxWithdrawalRequestsHeader() {
5 | return (
6 |
17 |
18 |
19 | Amount
20 |
21 |
22 |
23 |
24 | Withdraw on
25 |
26 |
27 | {/* no header for third column */}
28 |
29 | );
30 | }
31 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxGetAllWithdrawalRequests.ts:
--------------------------------------------------------------------------------
1 | import { useProvider } from 'wagmi';
2 | import { useQuery } from 'react-query';
3 | import { sftmxService } from '~/lib/services/staking/sftmx.service';
4 | import { BigNumber } from 'ethers';
5 |
6 | export function useSftmxGetAllWithdrawalRequests(wrId: string) {
7 | const provider = useProvider();
8 |
9 | return useQuery(
10 | ['sftmxGetAllWithdrawalRequests', wrId],
11 | async (): Promise<{
12 | requestTime: BigNumber;
13 | poolAmount: BigNumber;
14 | undelegateAmount: BigNumber;
15 | penalty: BigNumber;
16 | user: string;
17 | isWithdrawn: boolean;
18 | }> => sftmxService.getAllWithdrawalRequests({ wrId, provider }),
19 | { enabled: !!wrId },
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxGetCalculatePenalty.ts:
--------------------------------------------------------------------------------
1 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
2 | import { useProvider } from 'wagmi';
3 | import { useQuery } from 'react-query';
4 | import { BigNumber } from 'ethers';
5 | import { sftmxService } from '~/lib/services/staking/sftmx.service';
6 |
7 | export function useSftmxGetCalculatePenalty(amount: AmountHumanReadable) {
8 | const provider = useProvider();
9 |
10 | return useQuery(
11 | ['sftmxGetCalculatePenalty', amount],
12 | async (): Promise<{
13 | amountFtmReceived: BigNumber;
14 | amountUndelegated: BigNumber;
15 | amountPenalty: BigNumber;
16 | }> => sftmxService.getCalculatePenalty({ amount, provider }),
17 | { enabled: !!amount && amount !== '0' },
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxGetFtmxAmountForFtm.ts:
--------------------------------------------------------------------------------
1 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
2 | import { useProvider } from 'wagmi';
3 | import { useQuery } from 'react-query';
4 | import { BigNumber } from 'ethers';
5 | import { sftmxService } from '~/lib/services/staking/sftmx.service';
6 |
7 | export function useSftmxGetFtmxAmountForFtm(amount: AmountHumanReadable) {
8 | const provider = useProvider();
9 |
10 | return useQuery(
11 | ['sftmxGetFtmxAmountForFtm', amount],
12 | async (): Promise<{ amountSftmx: BigNumber }> => sftmxService.getFtmxAmountForFtm({ amount, provider }),
13 | { enabled: !!amount && amount !== '0' },
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxGetStakingData.ts:
--------------------------------------------------------------------------------
1 | import { useSftmxGetStakingDataQuery } from '~/apollo/generated/graphql-codegen-generated';
2 |
3 | export function useSftmxGetStakingData() {
4 | const { data, ...rest } = useSftmxGetStakingDataQuery();
5 |
6 | return {
7 | ...rest,
8 | data,
9 | };
10 | }
11 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxGetWithdrawalRequests.ts:
--------------------------------------------------------------------------------
1 | import { useSftmxGetWithdrawalRequestsQuery } from '~/apollo/generated/graphql-codegen-generated';
2 | import { useUserAccount } from '~/lib/user/useUserAccount';
3 | import { AddressZero } from '@ethersproject/constants';
4 |
5 | export function useSftmxGetWithdrawalRequests() {
6 | const { userAddress } = useUserAccount();
7 |
8 | const { data, ...rest } = useSftmxGetWithdrawalRequestsQuery({
9 | variables: { user: (userAddress || AddressZero) as string },
10 | });
11 |
12 | return { data, ...rest };
13 | }
14 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxStake.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import FTMStakingAbi from '~/lib/abi/FTMStaking.json';
3 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
4 | import { parseUnits } from 'ethers/lib/utils.js';
5 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
6 |
7 | export function useSftmxStake() {
8 | const networkConfig = useNetworkConfig();
9 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
10 | config: {
11 | addressOrName: networkConfig.sftmx.ftmStakingProxyAddress,
12 | contractInterface: FTMStakingAbi,
13 | functionName: 'deposit',
14 | },
15 | transactionType: 'STAKE',
16 | });
17 |
18 | function stake(amount: AmountHumanReadable) {
19 | submit({
20 | args: [],
21 | overrides: {
22 | value: parseUnits(amount, 18),
23 | },
24 | toastText: `Stake ${amount} FTM`,
25 | });
26 | }
27 |
28 | return {
29 | stake,
30 | ...rest,
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxUnstake.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import FTMStakingAbi from '~/lib/abi/FTMStaking.json';
3 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
4 | import { parseUnits } from 'ethers/lib/utils.js';
5 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
6 | import { BigNumber } from 'ethers';
7 |
8 | export function useSftmxUnstake() {
9 | const networkConfig = useNetworkConfig();
10 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
11 | config: {
12 | addressOrName: networkConfig.sftmx.ftmStakingProxyAddress,
13 | contractInterface: FTMStakingAbi,
14 | functionName: 'undelegate',
15 | },
16 | transactionType: 'UNSTAKE',
17 | });
18 |
19 | const wrID = `${Date.now()}`;
20 |
21 | function undelegate(amount: AmountHumanReadable, penalty: BigNumber) {
22 | submit({
23 | args: [wrID, parseUnits(amount, 18), penalty],
24 | toastText: `Unstake ${amount} FTM`,
25 | });
26 | }
27 |
28 | return {
29 | undelegate,
30 | ...rest,
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/modules/sftmx/lib/useSftmxWithdraw.ts:
--------------------------------------------------------------------------------
1 | import { useSubmitTransaction } from '~/lib/util/useSubmitTransaction';
2 | import FTMStakingAbi from '~/lib/abi/FTMStaking.json';
3 | import { AmountHumanReadable } from '~/lib/services/token/token-types';
4 | import { useNetworkConfig } from '~/lib/global/useNetworkConfig';
5 |
6 | export function useSftmxWithdraw() {
7 | const networkConfig = useNetworkConfig();
8 | const { submit, submitAsync, ...rest } = useSubmitTransaction({
9 | config: {
10 | addressOrName: networkConfig.sftmx.ftmStakingProxyAddress,
11 | contractInterface: FTMStakingAbi,
12 | functionName: 'withdraw',
13 | },
14 | transactionType: 'EXIT',
15 | });
16 |
17 | function withdraw(amount: AmountHumanReadable, wrId: string) {
18 | submit({
19 | args: [wrId, 0],
20 | toastText: `Withdraw ${amount} sFTMx`,
21 | });
22 | }
23 |
24 | return {
25 | withdraw,
26 | ...rest,
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/modules/sftmx/sftmx.gql:
--------------------------------------------------------------------------------
1 | query SftmxGetStakingData {
2 | sftmxGetStakingData {
3 | exchangeRate
4 | maintenancePaused
5 | maxDepositLimit
6 | minDepositLimit
7 | numberOfVaults
8 | stakingApr
9 | totalFtmAmount
10 | totalFtmAmountInPool
11 | totalFtmAmountStaked
12 | undelegatePaused
13 | withdrawPaused
14 | withdrawalDelay
15 | numberOfVaults
16 | vaults {
17 | ftmAmountStaked
18 | isMatured
19 | unlockTimestamp
20 | validatorAddress
21 | validatorId
22 | vaultAddress
23 | vaultIndex
24 | }
25 | }
26 | }
27 |
28 | query SftmxGetWithdrawalRequests($user: String!) {
29 | sftmxGetWithdrawalRequests(user: $user) {
30 | amountSftmx
31 | id
32 | isWithdrawn
33 | requestTimestamp
34 | user
35 | }
36 | }
37 |
38 | query SftmxGetStakingSnapshots($range: GqlSftmxStakingSnapshotDataRange!) {
39 | snapshots: sftmxGetStakingSnapshots(range: $range) {
40 | exchangeRate
41 | id
42 | timestamp
43 | totalFtmAmount
44 | totalFtmAmountInPool
45 | totalFtmAmountStaked
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | // This file sets a custom webpack configuration to use your Next.js app
2 | // with Sentry.
3 | // https://nextjs.org/docs/api-reference/next.config.js/introduction
4 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
5 | const { withSentryConfig } = require('@sentry/nextjs');
6 |
7 | /** @type {import('next').NextConfig} */
8 | const path = require('path');
9 | const transpiled = require('next-transpile-modules')(['echarts', 'zrender']);
10 |
11 | const nextConfig = {
12 | reactStrictMode: true,
13 | productionBrowserSourceMaps: true,
14 |
15 | webpack(config) {
16 | config.resolve.alias['~'] = path.join(__dirname, 'src');
17 | return config;
18 | },
19 |
20 | sentry: { hideSourcemaps: true, autoInstrumentServerFunctions: false },
21 |
22 | async redirects() {
23 | return [
24 | {
25 | source: '/',
26 | destination: '/pools',
27 | permanent: false,
28 | },
29 | {
30 | source: '/discord',
31 | destination: 'https://discord.gg/kbPnYJjvwZ',
32 | permanent: false,
33 | },
34 | ];
35 | },
36 | };
37 |
38 | const sentryWebpackPluginOptions = { silent: true };
39 |
40 | module.exports = withSentryConfig(transpiled(nextConfig), sentryWebpackPluginOptions);
41 |
--------------------------------------------------------------------------------
/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import Error from 'next/error';
2 |
3 | export default function NotFound() {
4 | // Opinionated: do not record an exception in Sentry for 404
5 | return ;
6 | }
7 |
--------------------------------------------------------------------------------
/pages/api/revalidate.ts:
--------------------------------------------------------------------------------
1 | import { NextApiRequest, NextApiResponse } from 'next';
2 |
3 | export default async function handler(req: NextApiRequest, res: NextApiResponse){
4 | // Check for secret to confirm this is a valid request
5 | if (req.query.secret !== process.env.REVALIDATION_SECRET) {
6 | return res.status(401).json({ message: 'Invalid token' })
7 | }
8 | if(!(typeof req.query.path === 'string')){
9 | return res.status(400).json({ message: `Invalid path argument: ${req.query.path}` })
10 | }
11 |
12 | try {
13 | // this should be the actual path not a rewritten path
14 | // e.g. for "/blog/[slug]" this should be "/blog/post-1"
15 | await res.revalidate(req.query.path)
16 | return res.json({ revalidated: true })
17 | } catch (err) {
18 | // If there was an error, Next.js will continue
19 | // to show the last successfully generated page
20 | return res.status(500).send('Error revalidating')
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 | import { useRouter } from 'next/router';
3 |
4 | function useV1Redirect() {
5 | const { push } = useRouter();
6 | const redirectChecked = useRef(false);
7 |
8 | useEffect(() => {
9 | if (typeof window !== 'undefined' && window.location.hash && !redirectChecked.current) {
10 | const hash = window.location.hash;
11 |
12 | redirectChecked.current = true;
13 |
14 | if (hash.indexOf('#/pool/') === 0) {
15 | const poolId = hash.slice(7, 74);
16 |
17 | push(`/pool/${poolId}`);
18 | } else if (hash.indexOf('#/pools') === 0) {
19 | push('/pools');
20 | } else if (hash.indexOf('#/trade') === 0) {
21 | push('/swap');
22 | }
23 | }
24 | });
25 | }
26 |
27 | function HomePage() {
28 | useV1Redirect();
29 |
30 | return null;
31 | }
32 |
33 | export default HomePage;
34 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/favicon.ico
--------------------------------------------------------------------------------
/public/fonts/gotham-bold-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-bold-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/gotham-bold-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-bold-webfont.woff2
--------------------------------------------------------------------------------
/public/fonts/gotham-book-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-book-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/gotham-book-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-book-webfont.woff2
--------------------------------------------------------------------------------
/public/fonts/gotham-light-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-light-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/gotham-light-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-light-webfont.woff2
--------------------------------------------------------------------------------
/public/fonts/gotham-medium-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-medium-webfont.woff
--------------------------------------------------------------------------------
/public/fonts/gotham-medium-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/fonts/gotham-medium-webfont.woff2
--------------------------------------------------------------------------------
/public/images/hero-image-fantom-mobile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/images/hero-image-fantom-mobile.jpg
--------------------------------------------------------------------------------
/public/images/hero-image-fantom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/images/hero-image-fantom.jpg
--------------------------------------------------------------------------------
/public/images/hero-image-optimism-mobile.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/images/hero-image-optimism-mobile.jpg
--------------------------------------------------------------------------------
/public/images/hero-image-optimism.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/beethovenxfi/beets-frontend/0b53ad4a691de2965e7b52d8ffd66f22416fc2bc/public/images/hero-image-optimism.jpg
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sentry.client.config.js:
--------------------------------------------------------------------------------
1 | // This file configures the initialization of Sentry on the browser.
2 | // The config you add here will be used whenever a page is visited.
3 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/
4 |
5 | import * as Sentry from '@sentry/nextjs';
6 |
7 | const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
8 |
9 | Sentry.init({
10 | dsn: SENTRY_DSN,
11 | // Adjust this value in production, or use tracesSampler for greater control
12 | tracesSampleRate: 1.0,
13 | // ...
14 | // Note: if you want to override the automatic release value, do not set a
15 | // `release` value here - use the environment variable `SENTRY_RELEASE`, so
16 | // that it will also get attached to your source maps
17 | beforeSend(event, hint) {
18 | const error = hint.originalException;
19 | if (
20 | error.name.toString().includes('TransactionError') &&
21 | !error.message.toString().includes('User rejected request')
22 | ) {
23 | return event;
24 | }
25 | return null;
26 | },
27 | });
28 |
--------------------------------------------------------------------------------
/sentry.edge.config.js:
--------------------------------------------------------------------------------
1 | // This file configures the initialization of Sentry on the server.
2 | // The config you add here will be used whenever middleware or an Edge route handles a request.
3 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/
4 |
5 | import * as Sentry from '@sentry/nextjs';
6 |
7 | const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
8 |
9 | Sentry.init({
10 | dsn: SENTRY_DSN,
11 | // Adjust this value in production, or use tracesSampler for greater control
12 | tracesSampleRate: 1.0,
13 | // ...
14 | // Note: if you want to override the automatic release value, do not set a
15 | // `release` value here - use the environment variable `SENTRY_RELEASE`, so
16 | // that it will also get attached to your source maps
17 | beforeSend(event, hint) {
18 | const error = hint.originalException;
19 | if (
20 | error.name.toString().includes('TransactionError') &&
21 | !error.message.toString().includes('User rejected request')
22 | ) {
23 | return event;
24 | }
25 | return null;
26 | },
27 | });
28 |
--------------------------------------------------------------------------------
/sentry.properties:
--------------------------------------------------------------------------------
1 | defaults.url=https://sentry.io/
2 | defaults.org=skloon
3 | defaults.project=frontend
4 | cli.executable=node_modules\\@sentry\\cli\\bin\\sentry-cli
5 |
--------------------------------------------------------------------------------
/sentry.server.config.js:
--------------------------------------------------------------------------------
1 | // This file configures the initialization of Sentry on the server.
2 | // The config you add here will be used whenever the server handles a request.
3 | // https://docs.sentry.io/platforms/javascript/guides/nextjs/
4 |
5 | import * as Sentry from '@sentry/nextjs';
6 |
7 | const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
8 |
9 | Sentry.init({
10 | dsn: SENTRY_DSN,
11 | // Adjust this value in production, or use tracesSampler for greater control
12 | tracesSampleRate: 1.0,
13 | // ...
14 | // Note: if you want to override the automatic release value, do not set a
15 | // `release` value here - use the environment variable `SENTRY_RELEASE`, so
16 | // that it will also get attached to your source maps
17 | beforeSend(event, hint) {
18 | const error = hint.originalException;
19 | if (
20 | error.name.toString().includes('TransactionError') &&
21 | !error.message.toString().includes('User rejected request')
22 | ) {
23 | return event;
24 | }
25 | return null;
26 | },
27 | });
28 |
--------------------------------------------------------------------------------
/styles/Reliquary.module.css:
--------------------------------------------------------------------------------
1 | .overlapGrid {
2 | display: grid;
3 | height: 200px;
4 | width: 400px;
5 | grid-template-areas: 'overlay';
6 | }
7 |
8 | .overlapGrid > div > div:nth-child(1),
9 | .overlapGrid > div > span:nth-child(1) {
10 | height: 200px !important;
11 | width: 200px !important;
12 | left: 100px;
13 | }
14 |
15 | .overlapGrid > div:nth-child(1),
16 | .overlapGrid > span:nth-child(1) {
17 | height: 200px !important;
18 | width: 450px !important;
19 | left: -25px;
20 | }
21 |
22 | @media only screen and (max-width: 400px) {
23 | .overlapGrid > div:nth-child(1),
24 | .overlapGrid > span:nth-child(1) {
25 | width: 90% !important;
26 | left: 15px;
27 | }
28 | }
29 |
30 | .overlapGrid > span,
31 | .overlapGrid > div {
32 | grid-area: overlay;
33 | }
34 |
--------------------------------------------------------------------------------
/styles/chakraTheme.ts:
--------------------------------------------------------------------------------
1 | // chakraTheme.ts
2 |
3 | // 1. import `extendTheme` function
4 | import { ComponentStyleConfig, extendTheme, ThemeConfig } from '@chakra-ui/react';
5 | import { fantomTheme } from '~/styles/themes/fantomTheme';
6 | import { optimismTheme } from '~/styles/themes/optimismTheme';
7 |
8 | // 2. Add your color mode config
9 | const config: ThemeConfig = {
10 | initialColorMode: 'dark',
11 | useSystemColorMode: false,
12 | };
13 |
14 | const siteTheme = process.env.NEXT_PUBLIC_CHAIN_ID === '10' ? optimismTheme : fantomTheme;
15 |
16 | // 3. extend the chakraTheme
17 | export const chakraTheme = extendTheme({
18 | ...siteTheme,
19 | config,
20 | components: {
21 | ...siteTheme.components,
22 | },
23 | });
24 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "baseUrl": "./",
18 | "paths": {
19 | "~/*": ["./*"]
20 | },
21 | "downlevelIteration": true
22 | },
23 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
24 | "exclude": ["node_modules"]
25 | }
26 |
--------------------------------------------------------------------------------
/types/react-table-config.d.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-table
2 | import {
3 | UseExpandedHooks,
4 | UseExpandedInstanceProps,
5 | UseExpandedOptions,
6 | UseExpandedRowProps,
7 | UseExpandedState,
8 | } from 'react-table';
9 |
10 | declare module 'react-table' {
11 | export interface TableOptions> extends UseExpandedOptions {}
12 |
13 | export interface Hooks = Record> extends UseExpandedHooks {}
14 |
15 | export interface TableInstance = Record>
16 | extends UseExpandedInstanceProps {}
17 |
18 | export interface TableState = Record>
19 | extends UseExpandedState {}
20 |
21 | export interface Row = Record> extends UseExpandedRowProps {}
22 | }
23 |
--------------------------------------------------------------------------------