diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 9fa08a629..0cf44f31c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,9 +1,9 @@ --- name: Bug report about: Create a report to help us improve -title: '' -labels: '' -assignees: '' +title: "" +labels: "" +assignees: "" --- **Describe the bug** A clear and concise description of what the bug is. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md index 96a47352a..babf9b2c0 100644 --- a/.github/ISSUE_TEMPLATE/custom.md +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -1,7 +1,7 @@ --- name: Custom issue template about: Describe this issue template's purpose here. -title: '' -labels: '' -assignees: '' +title: "" +labels: "" +assignees: "" --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 90320852b..3a3c1418e 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,9 +1,9 @@ --- name: Feature request about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' +title: "" +labels: "" +assignees: "" --- **Is your feature request related to a problem? Please describe.** A clear and concise description diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 05e0735bd..337a54cfc 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -21,4 +21,4 @@ runs: - name: Generate api typings shell: bash - run: pnpm graphql:gen + run: pnpm --filter lib graphql:gen diff --git a/apps/frontend-v3/LICENSE b/LICENSE similarity index 100% rename from apps/frontend-v3/LICENSE rename to LICENSE diff --git a/README.md b/README.md index b2b6362c2..fc71ba580 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ _This project uses `pnpm`, if you haven't already installed it you can find the documentation here: https://pnpm.io/installation_ -_The monorepo uses [pnpm workspaces](https://pnpm.io/workspaces) along with Turborepo to manage build orchestration, -to learn more about Turborepo please see the +_The monorepo uses [pnpm workspaces](https://pnpm.io/workspaces) along with Turborepo to manage +build orchestration, to learn more about Turborepo please see the [docs](https://turbo.build/repo/docs)._ ## What's inside? @@ -12,34 +12,40 @@ to learn more about Turborepo please see the This monorepo includes the following apps & packages: ### Apps -- [apps/frontend-v3](https://github.com/balancer/frontend-monorepo/tree/main/apps/frontend-v3): The official web app for the Balancer protocol, hosted at [https://balancer.fi](https://balancer.fi). +- [apps/frontend-v3](https://github.com/balancer/frontend-monorepo/tree/main/apps/frontend-v3): The + official web app for the Balancer protocol, hosted at [https://balancer.fi](https://balancer.fi). ### Packages -- [packages/eslint-config](https://github.com/balancer/frontend-monorepo/tree/main/packages/eslint-config): eslint configurations. -- [packages/typescript-config](https://github.com/balancer/frontend-monorepo/tree/main/packages/typescript-config): Typescript config's used throughout the monorepo. +- [packages/eslint-config](https://github.com/balancer/frontend-monorepo/tree/main/packages/eslint-config): + eslint configurations. +- [packages/typescript-config](https://github.com/balancer/frontend-monorepo/tree/main/packages/typescript-config): + Typescript config's used throughout the monorepo. ## Getting started -To set up a local environment for development, first clone the repo and navigate -to it in your console: +To set up a local environment for development, first clone the repo and navigate to it in your +console: ``` git clone https://github.com/balancer/frontend-monorepo.git && cd frontend-monorepo ``` Then create a local environment variable file for the `frontend-v3` app. + ``` cp apps/frontend-v3/.env.template apps/frontend-v3/.env.local ``` Install modules + ``` pnpm install ``` Then spin up the dev environment with: + ``` pnpm dev ``` @@ -57,6 +63,7 @@ pnpm build ### Testing To test all apps and packages, run: + ``` pnpm test:unit // or @@ -64,28 +71,37 @@ pnpm test:integration ``` ### Install a package -If you want to install a new npm package in a sub application like `frontend-v3` -add the --filter option to your install command, e.g.: + +If you want to install a new npm package in a sub application like `frontend-v3` add the --filter +option to your install command, e.g.: + ``` pnpm add some-pkg --filter=frontend-v3 ``` + This filter should match the `name` attribute in the app or package package.json. ## Turborepo ### Remote Caching -Turborepo can use a technique known as [Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. +Turborepo can use a technique known as +[Remote Caching](https://turbo.build/repo/docs/core-concepts/remote-caching) to share cache +artifacts across machines, enabling you to share build caches with your team and CI/CD pipelines. -By default, Turborepo will cache locally. To enable Remote Caching you will need an account with Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the following commands: +By default, Turborepo will cache locally. To enable Remote Caching you will need an account with +Vercel. If you don't have an account you can [create one](https://vercel.com/signup), then enter the +following commands: ``` npx turbo login ``` -This will authenticate the Turborepo CLI with your [Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). +This will authenticate the Turborepo CLI with your +[Vercel account](https://vercel.com/docs/concepts/personal-accounts/overview). -Next, you can link your Turborepo to your Remote Cache by running the following command from the root of your Turborepo: +Next, you can link your Turborepo to your Remote Cache by running the following command from the +root of your Turborepo: ``` npx turbo link diff --git a/apps/beets-frontend-v3/.env.template b/apps/beets-frontend-v3/.env.template new file mode 100644 index 000000000..5d2af7054 --- /dev/null +++ b/apps/beets-frontend-v3/.env.template @@ -0,0 +1,15 @@ +NEXT_PUBLIC_APP_ENV=dev +NEXT_PUBLIC_BALANCER_API_URL=https://api-v3.balancer.fi/graphql +NEXT_PUBLIC_WALLET_CONNECT_ID=1b6b722470b504a53cf011e1e629a9eb + +# For wallet checks (optional) +PRIVATE_HYPERNATIVE_API_ID=xxx +PRIVATE_HYPERNATIVE_API_SECRET=xxx + +# For fiat currency conversions (optional) +PRIVATE_CURRENCYAPI_KEY=xxx + +# For integration tests and rpc proxy routes (optional) +NEXT_PRIVATE_ALCHEMY_KEY=xxx + + diff --git a/apps/beets-frontend-v3/.env.test b/apps/beets-frontend-v3/.env.test new file mode 100644 index 000000000..e3ed2e3eb --- /dev/null +++ b/apps/beets-frontend-v3/.env.test @@ -0,0 +1,2 @@ +NEXT_PUBLIC_APP_ENV=test +NEXT_PUBLIC_BALANCER_API_URL=https://api-v3.balancer.fi/graphql diff --git a/apps/beets-frontend-v3/.eslintrc.js b/apps/beets-frontend-v3/.eslintrc.js new file mode 100644 index 000000000..b5f2a63ce --- /dev/null +++ b/apps/beets-frontend-v3/.eslintrc.js @@ -0,0 +1,9 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + extends: ['@repo/eslint-config/next.js'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: true, + }, +} diff --git a/apps/beets-frontend-v3/.gitignore b/apps/beets-frontend-v3/.gitignore new file mode 100644 index 000000000..b61c51b83 --- /dev/null +++ b/apps/beets-frontend-v3/.gitignore @@ -0,0 +1,48 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local +.env + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts + +.vscode +.idea + +# Sentry Config File +.sentryclirc + +# GrapgQL Codegen +/lib/shared/services/api/generated/ + +# Sentry Config File +.env.sentry-build-plugin diff --git a/apps/beets-frontend-v3/.husky/pre-commit b/apps/beets-frontend-v3/.husky/pre-commit new file mode 100644 index 000000000..888b40608 --- /dev/null +++ b/apps/beets-frontend-v3/.husky/pre-commit @@ -0,0 +1 @@ +pnpm lint-staged --cwd apps/frontend-v3 \ No newline at end of file diff --git a/apps/beets-frontend-v3/.prettierrc.json b/apps/beets-frontend-v3/.prettierrc.json new file mode 100644 index 000000000..be2a8ca1e --- /dev/null +++ b/apps/beets-frontend-v3/.prettierrc.json @@ -0,0 +1 @@ +"@repo/prettier-config" diff --git a/apps/beets-frontend-v3/.stylelintignore b/apps/beets-frontend-v3/.stylelintignore new file mode 100644 index 000000000..536d88c8a --- /dev/null +++ b/apps/beets-frontend-v3/.stylelintignore @@ -0,0 +1 @@ +.next/ diff --git a/apps/beets-frontend-v3/README.md b/apps/beets-frontend-v3/README.md new file mode 100644 index 000000000..99882a745 --- /dev/null +++ b/apps/beets-frontend-v3/README.md @@ -0,0 +1,43 @@ +# Balancer frontend V3 + +## Getting Started + +_This project uses `pnpm`, if you haven't already installed it you can find the documentation here: +https://pnpm.io/installation_ + +To setup the development environment, first clone the repo: + +```bash +git clone https://github.com/balancer/frontend-v3.git && cd frontend-v3 +``` + +Copy and rename the `.env.example` file to `.env.local`: + +```bash +cp .env.example .env.local +``` + +Next, install dependencies: + +```bash +pnpm install +``` + +Then, run the development server: + +```bash +pnpm dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +## Testing + +See [TESTING.md](./test/TESTING.md). + +## Developing in Windows + +To develop in Windows you need to use WSL2. Learn more about it +[here](https://learn.microsoft.com/en-us/windows/wsl/about). + +With WSL2 all environment variables will be correctly set without having to use `cross-env`. diff --git a/apps/beets-frontend-v3/app/(app)/debug/alerts/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/alerts/page.tsx new file mode 100644 index 000000000..c20690ee0 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/alerts/page.tsx @@ -0,0 +1,83 @@ +'use client' + +import { BalAlert } from '@repo/lib/shared/components/alerts/BalAlert' +import { BalAlertButton } from '@repo/lib/shared/components/alerts/BalAlertButton' +import { BalAlertContent } from '@repo/lib/shared/components/alerts/BalAlertContent' +import { useGlobalAlerts } from '@repo/lib/shared/components/alerts/GlobalAlertsProvider' +import { GenericError } from '@repo/lib/shared/components/errors/GenericError' +import { Button, VStack } from '@chakra-ui/react' + +const exceptionName = 'Error fetching swap' +const exceptionMessage = `Execution reverted for an unknown reason. Raw Call Arguments: +to:0xE39B5e3B6D74016b2F6A9673D7d7493B6DF549d5 +Docs: https://viem.sh/docs/contract/simulateContract Details: execution reverted Version: +viem@2.16.3` + +class TestError extends Error { + constructor(name: string, message: string) { + super(message) + this.name = name + } +} + +export default function Page() { + const { addAlert } = useGlobalAlerts() + return ( + + } status="info" /> + } status="warning" /> + } status="error" /> + } status="success" /> + + + + } + status="info" + /> + + + + + + ) +} + +function TitleWithButton({ title }: { title: string }) { + return ( + + console.log('Clicked')}>Click me + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/layout.tsx b/apps/beets-frontend-v3/app/(app)/debug/layout.tsx new file mode 100644 index 000000000..fa8f0dbf0 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/layout.tsx @@ -0,0 +1,6 @@ +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import { PropsWithChildren } from 'react' + +export default function DebugLayout({ children }: PropsWithChildren) { + return {children} +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/modal/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/modal/page.tsx new file mode 100644 index 000000000..5960c5177 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/modal/page.tsx @@ -0,0 +1,104 @@ +'use client' + +import { SuccessOverlay } from '@repo/lib/shared/components/modals/SuccessOverlay' +import { TransactionModalHeader } from '@repo/lib/shared/components/modals/TransactionModalHeader' +import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' +import { useDisclosure } from '@chakra-ui/hooks' +import { + Button, + Modal, + ModalContent, + ModalCloseButton, + ModalBody, + ModalFooter, + Box, +} from '@chakra-ui/react' +import { AnimatePresence, motion } from 'framer-motion' +import { useState } from 'react' +import useMeasure from 'react-use-measure' +import { Hex } from 'viem' + +export default function ModalPage() { + const { isOpen, onOpen, onClose } = useDisclosure() + const [txHash, setTxHash] = useState(undefined) + const [ref, { height }] = useMeasure() + + function toggleSuccess() { + setTxHash(txHash ? undefined : '0x123') + } + + return ( + <> + + + + + + + + + + + + {txHash ? ( + + + + ) : ( + + + + )} + + + + + + + + {txHash ? ( + + + + ) : ( + + + + )} + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/page.tsx new file mode 100644 index 000000000..70bffbe11 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/page.tsx @@ -0,0 +1,120 @@ +'use client' +import { Heading, VStack } from '@chakra-ui/react' +import NextLink from 'next/link' +import { Link } from '@chakra-ui/react' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' + +export default function Debug() { + return ( + + + Demos + + Sepolia V3 pool (Balancer 50 BAL 50 WETH) + + + Add liquidity in WEIGHTED (wjAura-weth) + + + Add liquidity in META_STABLE (wstETH_wETH) + + + Add liquidity in STABLE (B-rETH-STABLE in Mainnet) + + + Add liquidity in STABLE with BPT tokens (AuraBal 80/20 pool in Mainnet) + + + Add liquidity in STABLE (FRAX_USDC_MAI in Optimism) + + + Add liquidity in nested pool (50WETH-50-3pool) + + + Add liquidity in Gyro pool (2CLP-WSTETH-WETH in Mainnet) + + + Add liquidity in Gyro pool (2CLP_WMATIC/MATICX in Polygon) + + + Weighted Pool in recovery mode (not paused) + + + Composable Pool in recovery mode (not paused) + + + Pool with Merkl APR items (Fraxtal) + + + CoW AMM Pool (Sepolia) + + + Bricked Composable Stable Pool in recovery mode and paused + + + Old boosted pool with issues + + + Token select + + + Token input + + + Sentry + + + Wallet check + + + Alerts + + + Modal animation + + + Remove allowance + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/remove-allowance/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/remove-allowance/page.tsx new file mode 100644 index 000000000..9f6240a04 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/remove-allowance/page.tsx @@ -0,0 +1,51 @@ +'use client' + +import { buildTokenApprovalLabels } from '@repo/lib/modules/tokens/approvals/approval-labels' +import { TransactionStepButton } from '@repo/lib/modules/transactions/transaction-steps/TransactionStepButton' +import { useUserAccount } from '@repo/lib/modules/web3/UserAccountProvider' +import { + ManagedErc20TransactionInput, + useManagedErc20Transaction, +} from '@repo/lib/modules/web3/contracts/useManagedErc20Transaction' +import { sentryMetaForWagmiSimulation } from '@repo/lib/shared/utils/query-errors' +import { Center, Input, Text, VStack } from '@chakra-ui/react' +import { useState } from 'react' +import { Address } from 'viem' + +export default function Page() { + const [tokenAddress, setTokenAddress] = useState
('' as Address) + + const labels = buildTokenApprovalLabels({ actionType: 'Swapping', symbol: 'Token' }) + + const { chain, userAddress } = useUserAccount() + + const chainId = chain?.id || 1 + + const props: ManagedErc20TransactionInput = { + tokenAddress, + functionName: 'approve', + labels, + chainId, + args: [userAddress, 0n], + enabled: !!userAddress, + simulationMeta: sentryMetaForWagmiSimulation('Error in wagmi tx simulation: Approving token', { + tokenAmountToApprove: 0n, + }), + } + + const transaction = useManagedErc20Transaction(props) + + return ( +
+ + + Enter address of token to remove allowance in the current chain:{' '} + {chain ? chain.name : 'None'} + + setTokenAddress(e.target.value as Address)} /> + + + +
+ ) +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/sentry/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/sentry/page.tsx new file mode 100644 index 000000000..698ebd4a4 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/sentry/page.tsx @@ -0,0 +1,25 @@ +'use client' + +import { Button, Center } from '@chakra-ui/react' +import { SentryError, ensureError } from '@repo/lib/shared/utils/errors' + +export default function Page() { + function throwError() { + try { + throw new Error('Something low level') + } catch (err) { + const error = ensureError(err) + + throw new SentryError('Test error', { + cause: error, + context: { extra: { some: 'extra context' } }, + }) + } + } + + return ( +
+ +
+ ) +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/token-input/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/token-input/page.tsx new file mode 100644 index 000000000..62e8acaeb --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/token-input/page.tsx @@ -0,0 +1,65 @@ +'use client' + +import { useTokens } from '@repo/lib/modules/tokens/TokensProvider' +import { TokenInput } from '@repo/lib/modules/tokens/TokenInput/TokenInput' +import { Button, Card, Heading, Text, VStack, useDisclosure } from '@chakra-ui/react' +import { GqlChain, GqlToken } from '@repo/lib/shared/services/api/generated/graphql' +import { useState } from 'react' +import { TokenSelectModal } from '@repo/lib/modules/tokens/TokenSelectModal/TokenSelectModal' +import { TokenBalancesProvider } from '@repo/lib/modules/tokens/TokenBalancesProvider' +import { ConnectWallet } from '@repo/lib/modules/web3/ConnectWallet' +import { daiAddress } from '@repo/lib/debug-helpers' +import { TokenInputsValidationProvider } from '@repo/lib/modules/tokens/TokenInputsValidationProvider' +import { PriceImpactProvider } from '@repo/lib/modules/price-impact/PriceImpactProvider' + +export default function TokenInputPage() { + const [currentValue, setCurrentValue] = useState('') + const { getToken, getTokensByChain } = useTokens() + const tokenSelectDisclosure = useDisclosure() + const [token, setToken] = useState(getToken(daiAddress, 1) as GqlToken) + + const tokens = getTokensByChain(1) + + function handleTokenSelect(token: GqlToken) { + setToken(token) + } + + return ( + + + + + Token Input + Current value: {currentValue} + + + + setCurrentValue(e.currentTarget.value)} + toggleTokenSelect={() => { + tokenSelectDisclosure.onOpen() + }} + /> + + + + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/token-select/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/token-select/page.tsx new file mode 100644 index 000000000..00b686be3 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/token-select/page.tsx @@ -0,0 +1,39 @@ +'use client' + +import { TokenSelectModal } from '@repo/lib/modules/tokens/TokenSelectModal/TokenSelectModal' +import { TokenBalancesProvider } from '@repo/lib/modules/tokens/TokenBalancesProvider' +import { useTokens } from '@repo/lib/modules/tokens/TokensProvider' +import { GqlChain, GqlToken } from '@repo/lib/shared/services/api/generated/graphql' +import { Button, useDisclosure, Text } from '@chakra-ui/react' +import { useRef, useState } from 'react' + +export default function TokenSelectPage() { + const [selectedToken, setSelectedToken] = useState() + const tokenSelectBtn = useRef(null) + const tokenSelectDisclosure = useDisclosure() + const { getTokensByChain } = useTokens() + + function handleTokenSelect(token: GqlToken) { + setSelectedToken(token) + } + + return ( + +

TokenSelectPage

+ Selected token: {selectedToken?.symbol} + + +
+ ) +} diff --git a/apps/beets-frontend-v3/app/(app)/debug/wallet-check/page.tsx b/apps/beets-frontend-v3/app/(app)/debug/wallet-check/page.tsx new file mode 100644 index 000000000..694680660 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/debug/wallet-check/page.tsx @@ -0,0 +1,28 @@ +'use client' + +import { Box, Button, Code, Input, VStack } from '@chakra-ui/react' +import { useState } from 'react' + +export const dynamic = 'force-dynamic' + +export default function Page() { + const [address, setAddress] = useState('') + const [data, setData] = useState('') + + async function checkWallet() { + const res = await fetch(`/api/wallet-check/${address}`) + const data = await res.json() + setData(data) + console.log(data) + } + + return ( + + setAddress(e.target.value)} placeholder="0x..." /> + + + {JSON.stringify(data, null, 2)} + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/add-liquidity/[[...txHash]]/layout.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/add-liquidity/[[...txHash]]/layout.tsx new file mode 100644 index 000000000..98cb3a869 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/add-liquidity/[[...txHash]]/layout.tsx @@ -0,0 +1,52 @@ +'use client' + +import { isNotSupported, shouldBlockAddLiquidity } from '@repo/lib/modules/pool/pool.helpers' +import { usePool } from '@repo/lib/modules/pool/PoolProvider' +import { RelayerSignatureProvider } from '@repo/lib/modules/relayer/RelayerSignatureProvider' +import { TokenInputsValidationProvider } from '@repo/lib/modules/tokens/TokenInputsValidationProvider' +import { PriceImpactProvider } from '@repo/lib/modules/price-impact/PriceImpactProvider' +import { Alert } from '@chakra-ui/react' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' +import { PropsWithChildren } from 'react' +import { isHash } from 'viem' +import { usePoolRedirect } from '@repo/lib/modules/pool/pool.hooks' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import { AddLiquidityProvider } from '@repo/lib/modules/pool/actions/add-liquidity/AddLiquidityProvider' + +type Props = PropsWithChildren<{ + params: { txHash?: string[] } +}> + +export default function AddLiquidityLayout({ params: { txHash }, children }: Props) { + const { pool } = usePool() + const { redirectToPoolPage } = usePoolRedirect(pool) + + const maybeTxHash = txHash?.[0] || '' + const urlTxHash = isHash(maybeTxHash) ? maybeTxHash : undefined + + if (shouldBlockAddLiquidity(pool)) { + return redirectToPoolPage() + } + + if (isNotSupported(pool)) { + return ( + + This pool type is not currently supported in the Balancer V3 UI + + ) + } + + return ( + + + + + + {children} + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/add-liquidity/[[...txHash]]/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/add-liquidity/[[...txHash]]/page.tsx new file mode 100644 index 000000000..4df8dcd51 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/add-liquidity/[[...txHash]]/page.tsx @@ -0,0 +1,13 @@ +'use client' + +import { PoolActionsLayout } from '@repo/lib/modules/pool/actions/PoolActionsLayout' +import { AddLiquidityForm } from '@repo/lib/modules/pool/actions/add-liquidity/form/AddLiquidityForm' + +export default function AddLiquidityPage() { + // ./layout.tsx defines UI and state that is shared by this page and the nested /add-liquidity/[txHash] receipt page + return ( + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/error.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/error.tsx new file mode 100644 index 000000000..65eefa50e --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/error.tsx @@ -0,0 +1,5 @@ +'use client' + +import { PageErrorBoundary } from '@repo/lib/shared/components/errors/ErrorBoundary' + +export default PageErrorBoundary diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/layout.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/layout.tsx new file mode 100644 index 000000000..e84f2b73d --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/layout.tsx @@ -0,0 +1,81 @@ +/* eslint-disable max-len */ +import { FetchPoolProps } from '@repo/lib/modules/pool/pool.types' +import { ChainSlug, getPoolTypeLabel, slugToChainMap } from '@repo/lib/modules/pool/pool.utils' +import { PropsWithChildren, Suspense } from 'react' +import { PoolDetailSkeleton } from '@repo/lib/modules/pool/PoolDetail/PoolDetailSkeleton' +import { getApolloServerClient } from '@repo/lib/shared/services/api/apollo-server.client' +import { GetPoolDocument } from '@repo/lib/shared/services/api/generated/graphql' +import { Metadata } from 'next' +import { PoolProvider } from '@repo/lib/modules/pool/PoolProvider' +import { getProjectConfig } from '@repo/lib/config/getProjectConfig' +import { arrayToSentence } from '@repo/lib/shared/utils/strings' +import { ensureError } from '@repo/lib/shared/utils/errors' +import { notFound } from 'next/navigation' + +type Props = PropsWithChildren<{ + params: Omit & { chain: ChainSlug } +}> + +const { projectName } = getProjectConfig() + +async function getPoolQuery(chain: ChainSlug, id: string) { + const _chain = slugToChainMap[chain] + const variables = { id: id.toLowerCase(), chain: _chain } + + try { + const result = await getApolloServerClient().query({ + query: GetPoolDocument, + variables, + context: { + fetchOptions: { + next: { revalidate: 30 }, + }, + }, + }) + return { data: result.data, error: null } + } catch (error: unknown) { + return { data: null, error: ensureError(error) } + } +} + +export async function generateMetadata({ + params: { id, chain, variant }, +}: Props): Promise { + const { data } = await getPoolQuery(chain, id) + + const pool = data?.pool + if (!pool) return {} + + const poolTokenString = arrayToSentence(pool.displayTokens.map(token => token.symbol)) + + return { + title: `Liquidity Pool (${variant}): ${pool.name}`, + description: `${pool.symbol} is a ${projectName} ${variant} ${getPoolTypeLabel( + pool.type, + )} liquidity pool which contains ${poolTokenString}.`, + } +} + +export default async function PoolLayout({ params: { id, chain, variant }, children }: Props) { + const _chain = slugToChainMap[chain] + + const { data, error } = await getPoolQuery(chain, id) + + if (error) { + if (error?.message === 'Pool with id does not exist') { + notFound() + } + + throw new Error('Failed to fetch pool') + } else if (!data) { + throw new Error('Failed to fetch pool') + } + + return ( + }> + + {children} + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/migrate-stake/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/migrate-stake/page.tsx new file mode 100644 index 000000000..f547470b7 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/migrate-stake/page.tsx @@ -0,0 +1,21 @@ +'use client' + +import { PoolActionsLayout } from '@repo/lib/modules/pool/actions/PoolActionsLayout' +import { MigrateStakeForm } from '@repo/lib/modules/pool/actions/migrateStake/MigrateStakeForm' +import { MigrateStakeProvider } from '@repo/lib/modules/pool/actions/migrateStake/MigrateStakeProvider' +import { UnstakeProvider } from '@repo/lib/modules/pool/actions/unstake/UnstakeProvider' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' + +export default function MigrateStakePage() { + return ( + + + + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/opengraph-image.jpg b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/opengraph-image.jpg new file mode 100644 index 000000000..8bf26e872 Binary files /dev/null and b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/opengraph-image.jpg differ diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/page.tsx new file mode 100644 index 000000000..f907e8921 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/page.tsx @@ -0,0 +1,10 @@ +import { PoolDetail } from '@repo/lib/modules/pool/PoolDetail/PoolDetail' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' + +export default function PoolPage() { + return ( + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/remove-liquidity/[[...txHash]]/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/remove-liquidity/[[...txHash]]/page.tsx new file mode 100644 index 000000000..242276dbb --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/remove-liquidity/[[...txHash]]/page.tsx @@ -0,0 +1,35 @@ +'use client' + +import { PoolActionsLayout } from '@repo/lib/modules/pool/actions/PoolActionsLayout' +import { RemoveLiquidityForm } from '@repo/lib/modules/pool/actions/remove-liquidity/form/RemoveLiquidityForm' +import { RemoveLiquidityProvider } from '@repo/lib/modules/pool/actions/remove-liquidity/RemoveLiquidityProvider' +import { RelayerSignatureProvider } from '@repo/lib/modules/relayer/RelayerSignatureProvider' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' +import { PriceImpactProvider } from '@repo/lib/modules/price-impact/PriceImpactProvider' +import { isHash } from 'viem' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' + +type Props = { + params: { txHash?: string[] } +} + +export default function RemoveLiquidityPage({ params: { txHash } }: Props) { + const maybeTxHash = txHash?.[0] || '' + const urlTxHash = isHash(maybeTxHash) ? maybeTxHash : undefined + + return ( + + + + + + + + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/stake/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/stake/page.tsx new file mode 100644 index 000000000..29cc70532 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/stake/page.tsx @@ -0,0 +1,22 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +'use client' + +import { PoolActionsLayout } from '@repo/lib/modules/pool/actions/PoolActionsLayout' +import { StakeForm } from '@repo/lib/modules/pool/actions/stake/StakeForm' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' +import { StakeProvider } from '@repo/lib/modules/pool/actions/stake/StakeProvider' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' + +export default function StakePage() { + return ( + + + + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/unstake/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/unstake/page.tsx new file mode 100644 index 000000000..a1cd1d9f8 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/unstake/page.tsx @@ -0,0 +1,21 @@ +'use client' + +import { PoolActionsLayout } from '@repo/lib/modules/pool/actions/PoolActionsLayout' +import { UnstakeForm } from '@repo/lib/modules/pool/actions/unstake/UnstakeForm' +import { UnstakeProvider } from '@repo/lib/modules/pool/actions/unstake/UnstakeProvider' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' + +export default function UnstakePage() { + return ( + + + + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/cow/opengraph-image.png b/apps/beets-frontend-v3/app/(app)/pools/cow/opengraph-image.png new file mode 100644 index 000000000..eff224d69 Binary files /dev/null and b/apps/beets-frontend-v3/app/(app)/pools/cow/opengraph-image.png differ diff --git a/apps/beets-frontend-v3/app/(app)/pools/cow/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/cow/page.tsx new file mode 100644 index 000000000..6e15a85c0 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/cow/page.tsx @@ -0,0 +1,48 @@ +import { PoolList } from '@repo/lib/modules/pool/PoolList/PoolList' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' +import { GqlPoolType } from '@repo/lib/shared/services/api/generated/graphql' +import { Box, Skeleton } from '@chakra-ui/react' +import { Suspense } from 'react' +import { Metadata } from 'next' +import { CowFooter } from '@repo/lib/shared/components/navs/CowFooter' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import { CowHeader } from '@repo/lib/shared/components/header/CowHeader' + +export const metadata: Metadata = { + title: `CoW AMM DeFi Liquidity Pools`, + description: ` + CoW AMM protects LPs from LVR so they can provide liquidity + with less risk and more return. + `, +} + +export default function PoolsPage() { + return ( + <> + + + + + + + + + + + + + }> + + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/layout.tsx b/apps/beets-frontend-v3/app/(app)/pools/layout.tsx new file mode 100644 index 000000000..bd1422796 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/layout.tsx @@ -0,0 +1,18 @@ +import { getProjectConfig } from '@repo/lib/config/getProjectConfig' +import { Metadata } from 'next' +import { PropsWithChildren } from 'react' + +const { projectName } = getProjectConfig() + +export const metadata: Metadata = { + title: `${projectName} DeFi Liquidity Pools`, + description: ` + Explore DeFi liquidity pools or create your own. + Provide liquidity to accumulate yield from swap fees + while retaining your token exposure as prices move. + `, +} + +export default async function Pools({ children }: PropsWithChildren) { + return <>{children} +} diff --git a/apps/beets-frontend-v3/app/(app)/pools/page.tsx b/apps/beets-frontend-v3/app/(app)/pools/page.tsx new file mode 100644 index 000000000..6bd062ee8 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/pools/page.tsx @@ -0,0 +1,56 @@ +import { PoolList } from '@repo/lib/modules/pool/PoolList/PoolList' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' + +import { Box, Skeleton } from '@chakra-ui/react' +import { Suspense } from 'react' + +// import { getApolloServerClient } from '@repo/lib/shared/services/api/apollo-server.client' +// import { getProjectConfig } from '@repo/lib/config/getProjectConfig' +// import { GetFeaturedPoolsDocument } from '@repo/lib/shared/services/api/generated/graphql' +// import { FeaturedPools } from '@repo/lib/modules/featured-pools/FeaturedPools' +import { CowGalxeQuestPromoBanner } from '@repo/lib/shared/components/promos/CowGalxeQuestPromoBanner' + +export default async function PoolsPage() { + // Featured pools set up + // const { supportedNetworks } = getProjectConfig() + + // const featuredPoolsQuery = await getApolloServerClient().query({ + // query: GetFeaturedPoolsDocument, + // variables: { chains: supportedNetworks }, + // context: { + // fetchOptions: { + // next: { revalidate: 300 }, // 5 minutes + // }, + // }, + // }) + + // const featuredPools = featuredPoolsQuery.data.featuredPools || [] + + return ( + <> + + + + + + + + {/* + + + + */} + + + + + + }> + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/portfolio/[chain]/page.tsx b/apps/beets-frontend-v3/app/(app)/portfolio/[chain]/page.tsx new file mode 100644 index 000000000..ae4b0325d --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/portfolio/[chain]/page.tsx @@ -0,0 +1,131 @@ +'use client' +import { PoolName } from '@repo/lib/modules/pool/PoolName' +import { Pool } from '@repo/lib/modules/pool/PoolProvider' +import { ClaimModal } from '@repo/lib/modules/pool/actions/claim/ClaimModal' +import { ClaimProvider } from '@repo/lib/modules/pool/actions/claim/ClaimProvider' +import { ChainSlug, slugToChainMap } from '@repo/lib/modules/pool/pool.utils' +// eslint-disable-next-line max-len +import { ClaimNetworkPoolsLayout } from '@repo/lib/modules/portfolio/PortfolioClaim/ClaimNetworkPools/ClaimNetworkPoolsLayout' +import { usePortfolio } from '@repo/lib/modules/portfolio/PortfolioProvider' +import { TokenIconStack } from '@repo/lib/modules/tokens/TokenIconStack' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' +import { NetworkIcon } from '@repo/lib/shared/components/icons/NetworkIcon' +import { useCurrency } from '@repo/lib/shared/hooks/useCurrency' +import { Button, Card, HStack, Heading, Skeleton, Stack, Text, VStack } from '@chakra-ui/react' +import { capitalize } from 'lodash' +import { useParams } from 'next/navigation' +import { useState } from 'react' + +export default function NetworkClaim() { + const { toCurrency } = useCurrency() + const { chain } = useParams() + const { + poolsByChainMap, + poolRewardsMap, + totalFiatClaimableBalanceByChain, + isLoadingRewards, + refetchClaimPoolData, + } = usePortfolio() + + const gqlChain = slugToChainMap[chain as ChainSlug] + const pools = poolsByChainMap[gqlChain] + const chainName = capitalize(chain as string) + const claimableFiatBalance = totalFiatClaimableBalanceByChain[gqlChain] + + const isClaimAllDisabled = pools?.every(pool => + poolRewardsMap[pool.id]?.totalFiatClaimBalance?.isEqualTo(0), + ) + + const [modalPools, setModalPools] = useState([]) + + const hasMultipleClaims = pools ? pools.length > 1 : false + + return ( + + + + + + + {chainName} incentives + + + + {claimableFiatBalance && toCurrency(claimableFiatBalance)} + + + + {isLoadingRewards ? ( + + ) : pools && pools.length > 0 ? ( + pools?.map( + pool => + poolRewardsMap[pool.id]?.totalFiatClaimBalance?.isGreaterThan(0) && ( + + + + + + {toCurrency( + poolRewardsMap[pool.id]?.totalFiatClaimBalance?.toNumber() || 0, + )} + + + + + {hasMultipleClaims && ( + + )} + + + + ), + ) + ) : ( + + You have no liquidity incentives to claim + + )} + + {pools && pools.length > 0 && ( + + )} + {modalPools.length > 0 && ( + + 0} + onClose={(isSuccess: boolean) => { + if (isSuccess) { + refetchClaimPoolData() + } + + setModalPools([]) + }} + chain={gqlChain} + /> + + )} + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/portfolio/layout.tsx b/apps/beets-frontend-v3/app/(app)/portfolio/layout.tsx new file mode 100644 index 000000000..81aec2bce --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/portfolio/layout.tsx @@ -0,0 +1,11 @@ +import { PortfolioProvider } from '@repo/lib/modules/portfolio/PortfolioProvider' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import { PropsWithChildren } from 'react' + +export default async function PortfolioLayout({ children }: PropsWithChildren) { + return ( + + {children} + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/portfolio/page.tsx b/apps/beets-frontend-v3/app/(app)/portfolio/page.tsx new file mode 100644 index 000000000..c6519bf8a --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/portfolio/page.tsx @@ -0,0 +1,7 @@ +'use client' + +import Portfolio from '@repo/lib/modules/portfolio/Portfolio' + +export default function PortfolioPage() { + return +} diff --git a/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/getSwapPathParams.spec.ts b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/getSwapPathParams.spec.ts new file mode 100644 index 000000000..618d81420 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/getSwapPathParams.spec.ts @@ -0,0 +1,35 @@ +import { getSwapPathParams } from './getSwapPathParams' +import { describe, expect, it } from 'vitest' + +describe('Parses swap params from the url slug when', () => { + it('slug is undefined', () => { + expect(getSwapPathParams()).toEqual({}) + }) + it('slug is empty', () => { + expect(getSwapPathParams([])).toEqual({}) + }) + it('slug contains only chain', () => { + expect(getSwapPathParams(['ethereum'])).toEqual({ + chain: 'ethereum', + }) + }) + it('slug contains chain and txHash', () => { + expect( + getSwapPathParams([ + 'ethereum', + '0x11380dcffb24c512da18f032d9f7354d154cfda6bbab0633df182fcd202c4244', + ]) + ).toEqual({ + chain: 'ethereum', + urlTxHash: '0x11380dcffb24c512da18f032d9f7354d154cfda6bbab0633df182fcd202c4244', + }) + }) + it('slug contains chain and tokenIn', () => { + expect(getSwapPathParams(['ethereum', 'USDC', 'DAI', '123'])).toEqual({ + chain: 'ethereum', + tokenIn: 'USDC', + tokenOut: 'DAI', + amountIn: '123', + }) + }) +}) diff --git a/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/getSwapPathParams.ts b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/getSwapPathParams.ts new file mode 100644 index 000000000..f3085b0af --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/getSwapPathParams.ts @@ -0,0 +1,15 @@ +import { PathParams } from '@repo/lib/modules/swap/SwapProvider' +import { isHash } from 'viem' + +export function getSwapPathParams(slug?: string[]): PathParams { + const [chain, ...rest] = slug ?? [] + + if (!rest?.length) return { chain } + const maybeTxHash = rest[0] + const urlTxHash = isHash(maybeTxHash) ? maybeTxHash : undefined + if (urlTxHash) { + return { chain, urlTxHash } + } + const [tokenIn, tokenOut, amountIn, amountOut] = rest ?? [] + return { chain, tokenIn, tokenOut, amountIn, amountOut } +} diff --git a/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/layout.tsx b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/layout.tsx new file mode 100644 index 000000000..cd0a37b82 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/layout.tsx @@ -0,0 +1,44 @@ +'use client' + +import { ChainSlug, slugToChainMap } from '@repo/lib/modules/pool/pool.utils' +import { SwapProvider } from '@repo/lib/modules/swap/SwapProvider' +import { TokenBalancesProvider } from '@repo/lib/modules/tokens/TokenBalancesProvider' +import { TokenInputsValidationProvider } from '@repo/lib/modules/tokens/TokenInputsValidationProvider' +import { useTokens } from '@repo/lib/modules/tokens/TokensProvider' +import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' +import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' +import { PropsWithChildren } from 'react' +import { PriceImpactProvider } from '@repo/lib/modules/price-impact/PriceImpactProvider' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import { getSwapPathParams } from './getSwapPathParams' +import { RelayerSignatureProvider } from '@repo/lib/modules/relayer/RelayerSignatureProvider' + +type Props = PropsWithChildren<{ + params: { slug?: string[] } +}> + +export default function SwapLayout({ params: { slug }, children }: Props) { + const pathParams = getSwapPathParams(slug) + + const { getTokensByChain } = useTokens() + const initChain = pathParams.chain + ? slugToChainMap[pathParams.chain as ChainSlug] + : GqlChain.Mainnet + const initTokens = getTokensByChain(initChain) + + return ( + + + + + + + {children} + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/page.tsx b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/page.tsx new file mode 100644 index 000000000..e3e3c9372 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/swap/[[...slug]]/page.tsx @@ -0,0 +1,16 @@ +/* eslint-disable max-len */ + +import { getProjectConfig } from '@repo/lib/config/getProjectConfig' +import { SwapForm } from '@repo/lib/modules/swap/SwapForm' +import { Metadata } from 'next' + +const { projectName } = getProjectConfig() + +export const metadata: Metadata = { + title: `Swap tokens on ${projectName}`, + description: `Swap tokens on networks like Ethereum, Optimism, Arbitrum and Base via the Balancer decentralized exchange`, +} + +export default function SwapPage() { + return +} diff --git a/apps/beets-frontend-v3/app/(app)/vebal/layout.tsx b/apps/beets-frontend-v3/app/(app)/vebal/layout.tsx new file mode 100644 index 000000000..7e4703fe7 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/vebal/layout.tsx @@ -0,0 +1,25 @@ +'use client' + +import { TokenBalancesProvider } from '@repo/lib/modules/tokens/TokenBalancesProvider' +import { useTokens } from '@repo/lib/modules/tokens/TokensProvider' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import mainnetNetworkConfig from '@repo/lib/config/networks/mainnet' +import { PropsWithChildren } from 'react' + +export default function VebalLayout({ children }: PropsWithChildren) { + const { getTokensByChain } = useTokens() + + const tokens = getTokensByChain(1) + + const vebalBptToken = tokens.find( + t => t.address === mainnetNetworkConfig.tokens.addresses.veBalBpt, + ) + + if (!vebalBptToken) throw new Error('vebalBptToken not found') + + return ( + + {children} + + ) +} diff --git a/apps/beets-frontend-v3/app/(app)/vebal/page.tsx b/apps/beets-frontend-v3/app/(app)/vebal/page.tsx new file mode 100644 index 000000000..27054ca64 --- /dev/null +++ b/apps/beets-frontend-v3/app/(app)/vebal/page.tsx @@ -0,0 +1,12 @@ +'use client' + +import { VebalInfo } from '@repo/lib/modules/vebal/VebalInfo' +import { Stack } from '@chakra-ui/react' + +export default function VebalPage() { + return ( + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(marketing)/3rd-party-services/page.tsx b/apps/beets-frontend-v3/app/(marketing)/3rd-party-services/page.tsx new file mode 100644 index 000000000..f09c70bd8 --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/3rd-party-services/page.tsx @@ -0,0 +1,96 @@ +'use client' + +import { Container, HStack, VStack, Image, Text } from '@chakra-ui/react' +import { Prose } from '@nikolovlazar/chakra-ui-prose' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' + +export default function Cookies() { + const services = [ + { + name: 'Infura', + description: 'Used to fetch on-chain data and constructs contract calls with an Infura API.', + iconUrl: '/images/services/infura.svg', + }, + { + name: 'Alchemy', + description: 'Used to fetch on-chain data and constructs contract calls with an Alchemy API.', + iconUrl: '/images/services/alchemy.svg', + }, + { + name: 'The Graph', + description: 'Used to fetch blockchain data from The Graph’s hosted service.', + iconUrl: '/images/services/the-graph.svg', + }, + { + name: 'Fathom Analytics', + description: 'Used to understand user behavior on the site and marketing performance.', + iconUrl: '/images/services/fathom-analytics.svg', + }, + { + name: 'Appzi', + description: 'Used to capture and store user feedback from optional surveys', + iconUrl: '/images/services/appzi.svg', + }, + { + name: 'Hypernative', + description: + 'Used to securely check wallet addresses and shares it with Hypernative Inc. for risk and compliance reasons.', + iconUrl: '/images/services/hypernative.svg', + }, + { + name: 'Sentry', + description: 'Used for error tracking and performance monitoring.', + iconUrl: '/images/services/sentry.svg', + }, + { + name: 'Amazon Web Services', + description: + 'Used for a variety of infrastructure services, but primarily to fetch and cache blockchain data.', + iconUrl: '/images/services/aws.svg', + }, + ] + + return ( + + +
+ +
+

Use of 3rd party services

+

+ Last Updated: October 2023 +

+

+ Balancer is an open source, permissionless, decentralized protocol. The smart + contracts that power the ecosystem may be used by anyone. This website is the + Balancer Foundation's front-end to the ecosystem and it is also open-source. + You are free to fork it on Github and modify it as you wish. +

+

This website uses the following 3rd party services:

+ + {services.map(service => ( + + {service.name} + + + {service.name} + + + {service.description} + + + + ))} + +
+
+
+
+
+ ) +} diff --git a/apps/beets-frontend-v3/app/(marketing)/components/SandPatterns.tsx b/apps/beets-frontend-v3/app/(marketing)/components/SandPatterns.tsx new file mode 100644 index 000000000..bef1af8d3 --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/components/SandPatterns.tsx @@ -0,0 +1,69 @@ +import React, { PropsWithChildren } from 'react' +import { Box, Flex } from '@chakra-ui/react' +import { motion, MotionStyle, useAnimation, useReducedMotion } from 'framer-motion' + +const SandPatterns: React.FC = ({ children, ...rest }) => { + const circles = Array.from({ length: 10 }, (_, i) => i + 1) + const controls = useAnimation() + const shouldReduceMotion = useReducedMotion() + + const circleStyle: MotionStyle = { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + border: `1px solid var(--chakra-colors-input-borderDefault)`, + backgroundColor: 'transparent', + zIndex: '-10', + } + + React.useEffect(() => { + if (!shouldReduceMotion) { + controls.start(i => { + const calculatedWidth = 30 * (1 + 0.25 * i) + return { + width: [`${calculatedWidth}vw`], + height: [`${calculatedWidth}vw`], + borderRadius: ['10%', '50%', '10%'], + opacity: 1 - i * 0.1, + transition: { + duration: 90, + repeat: Infinity, + repeatType: 'reverse', + delay: i * 1.5, + ease: 'easeOut', + }, + } + }) + } + }, [controls, shouldReduceMotion]) + + return ( + + {circles.map((_, index) => ( + + ))} + + {children} + + + ) +} + +export default SandPatterns diff --git a/apps/beets-frontend-v3/app/(marketing)/components/page.tsx b/apps/beets-frontend-v3/app/(marketing)/components/page.tsx new file mode 100644 index 000000000..f38b1f103 --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/components/page.tsx @@ -0,0 +1,1266 @@ +'use client' + +import { + Text, + Center, + Heading, + Box, + Button, + Flex, + Input, + InputGroup, + InputRightElement, + Select, + UnorderedList, + ListItem, + Stack, + Avatar, + Card, + Checkbox, + Radio, + RadioGroup, + CardHeader, + CardBody, + Link, + CardFooter, + Image, + Slider, + SliderTrack, + SliderFilledTrack, + SliderThumb, + Tag, + Alert, + AlertIcon, + AlertTitle, + AlertDescription, + FormControl, + FormLabel, + FormErrorMessage, + FormHelperText, +} from '@chakra-ui/react' + +import { darken } from '@chakra-ui/theme-tools' +import Section from '@repo/lib/shared/components/layout/Section' + +export default function Components() { + return ( + + + + Components + + + Contents + + + + Colors + + + Typography + + + Buttons + + + Radius + + + Elevation + + + Shadows + + + Alerts + + + Cards + + + + Form fields + + + + +
+ + Colors + + +
+ Primary + +
+ 50 +
+ +
+ 100 +
+ +
+ 200 +
+ +
+ 300 +
+ +
+ 400 +
+ +
+ 500 +
+ +
+ 600 +
+ +
+ 700 +
+
+ 800 +
+
+ 900 +
+
+
+ +
+ Gray + +
+ 50 +
+ +
+ 100 +
+ +
+ 200 +
+ +
+ 300 +
+ +
+ 400 +
+ +
+ 500 +
+ +
+ 600 +
+ +
+ 700 +
+
+ 800 +
+
+ 900 +
+
+
+ +
+ Brown + +
+ 50 +
+
+ 100 +
+
+ 200 +
+
+ 300 +
+
+ 400 +
+
+ 500 +
+
+ 600 +
+
+ 700 +
+
+ 800 +
+
+ 900 +
+
+
+ +
+ Orange + +
+ 50 +
+ +
+ 100 +
+ +
+ 200 +
+ +
+ 300 +
+ +
+ 400 +
+ +
+ 500 +
+ +
+ 600 +
+ +
+ 700 +
+
+ 800 +
+
+ 900 +
+
+
+ +
+ Red + +
+ 50 +
+
+ 100 +
+
+ 200 +
+
+ 300 +
+
+ 400 +
+
+ 500 +
+
+ 600 +
+
+ 700 +
+
+ 800 +
+
+ 900 +
+
+
+
+ Purple + +
+ 50 +
+
+ 100 +
+
+ 200 +
+
+ 300 +
+
+ 400 +
+
+ 500 +
+
+ 600 +
+
+ 700 +
+
+ 800 +
+
+ 900 +
+
+
+
+ Green + +
+ 50 +
+
+ 100 +
+
+ 200 +
+
+ 300 +
+
+ 400 +
+
+ 500 +
+
+ 600 +
+
+ 700 +
+
+ 800 +
+
+ 900 +
+
+
+
+ Gradients + + +
+ Background special +
+
+ +
+ Background special secondary +
+
+
+
+ +
+ + Typography + + + + H1 Hero + + Hero heading 1 + + + + + H1 + + Default app Heading 1 + + + + + H2 + + Heading 2 + + + + + H3 + + Heading 3 + + + + + H4 + + Heading 4 + + + + + H5 + + Heading 5 + + + + + H6 + + Heading 6 + + + + + P + + Body text lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora quidem ipsa + magnam dignissimos impedit odit tempore, necessitatibus provident cupiditate. Explicabo + iusto incidunt illum molestiae, dolores quam odit cupiditate id quibusdam! + + + + Text secondary + + Body text lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora quidem ipsa + magnam dignissimos impedit odit tempore, necessitatibus provident cupiditate. Explicabo + iusto incidunt illum molestiae, dolores quam odit cupiditate id quibusdam! + + + + Text error + + Body text lorem ipsum dolor sit amet consectetur adipisicing elit. + + + + Text special + + Body text lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora quidem ipsa + magnam dignissimos impedit odit tempore, necessitatibus provident cupiditate. Explicabo + iusto incidunt illum molestiae, dolores quam odit cupiditate id quibusdam! + + + + Text special secondary + + Body text lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora quidem ipsa + magnam dignissimos impedit odit tempore, necessitatibus provident cupiditate. Explicabo + iusto incidunt illum molestiae, dolores quam odit cupiditate id quibusdam! + + + + Unordered list items + + To do + + + + Colors + + + Typography + + + Buttons + + + Cards + + + Inputs + + + + + Link + + + Cookies policy + + + + + External link + + Learn more on Aura + + + + Eyebrow + Lorem ipsum + +
+ +
+ + Buttons + +
+ + Button sizes + + + + + + + +
+
+ + Button variants + + + + + + + +
+
+ + Custom{' '} + + + + + + +
+
+ +
+ + Border Radius + + +
+ none +
+
+ +
sm
+
2px
+
+
+
+ +
base
+
4px
+
+
+
+ +
lg
+
8px
+
+
+
+ +
xl
+
12px
+
+
+
+ +
2xl
+
16px
+
+
+
+ +
3xl
+
20px
+
+
+
+ +
full
+
9999px
+
+
+
+
+ +
+ + Elevation + + 8 level elevation system + + + Background color is determined by height. + + The higher it is, the lighter the color. + + + + Shadows are relative. + + + The shadow size is dependent on the relative distance between it and the next level. + + + + + Card colors +
+ + + Card level 0 + + + Card level 1 + + + Card level 2 + + + Card level 3 + + + Card level 4 + + + + + + + + + + +
+
+ +
+ + Shadows + + + + + xs + + + + + sm + + + + + base + + + + + md + + + + + lg + + + + + xl + + + + + 2xl + + + + + dark-lg + + + + + + + outline + + + + + inner base + + + + + inner + + + + + innerSm + + + + + innerMd + + + + + innerLg + + + +
+ +
+ + Alerts + +
+ + + Your browser is outdated! + Your Chakra experience may be degraded. + +
+ +
+ + + Your browser is outdated! + Your Chakra experience may be degraded. + +
+
+ + + Your browser is outdated! + Your Chakra experience may be degraded. + +
+ +
+ + + Your browser is outdated! + A tip or piece of information. + +
+
+ +
+ + Cards + + + + + + + + + Title + Subtitle + + + + + + + lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora quidem ipsa magnam + dignissimos impedit odit tempore, necessitatibus provident cupiditate. Explicabo iusto + incidunt illum molestiae, dolores quam odit cupiditate id quibusdam! + + + Chakra UI + + button': { + minW: '136px', + }, + }} + > + + + + + +
+ +
+ + Form fields + + + + + Custom input fields + + + For some reason, I haven't been able to get some of these styles into the theme, so + I've listed all the code below + + + +
+
+ + + Input label + + + + {/* */} + {/* This doesn't work, but color="yellow" does work... */} + + + + Hint text that is displayed on focus of the input + + + +
+
+ + Input label + + + Exceeds wallet balance + + +
+
+ + + Disabled input label + + + +
+
+ + + + Theme inputs + + This is how it comes out of the theme. + + + + + Input + + + + + + + Disabled input + + + + + + + Select + + + + + + + Checkbox + + + Checkbox + Checkbox + + + + + + Radios + + + + + Checked + + Unchecked + Unchecked + + + + + + + Slider + + + + + + + + +
+
+ ) +} diff --git a/apps/beets-frontend-v3/app/(marketing)/cookies-policy/page.tsx b/apps/beets-frontend-v3/app/(marketing)/cookies-policy/page.tsx new file mode 100644 index 000000000..4036767ba --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/cookies-policy/page.tsx @@ -0,0 +1,122 @@ +'use client' + +import Link from 'next/link' +import { Container } from '@chakra-ui/react' +import { Prose } from '@nikolovlazar/chakra-ui-prose' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' + +export default function Cookies() { + return ( + + +
+ +
+

Balancer Cookies Policy

+

+ Last Updated: October 2023 +

+
+
+ +
+

I. Introduction and Scope of Policy

+

+ This Cookies Policy (“Policy”) applies to your interaction with the Balancer + Foundation, its subsidiary, Balancer OpCo Limited, and material service providers + operating under a legal agreement (“Balancer Foundation,” “Balancer,” “we,” “our,” + or “us”). +

+
+
+ +
+

II. About Cookies

+

+ Cookies are pieces of data stored on your device. Browser cookies are assigned by a + web server to the browser on your device. When you return to a site you have visited + before, your browser gives this data back to the server. Mobile applications may + also use cookies. +

+ +

+ We do not generally use cookies; however our third party vendors do. We do not + intentionally collect information to customize your experience on the website or the + Balancer.fi user interface (UI) to the Balancer Protocol. (“Sites” or “Site”). +

+

+ Industry standards are currently evolving, and we may not separately respond to or + take any action with respect to a “do not track” configuration set in your internet + browser. +

+

+ Other parties that collect information about your web browsing behavior when you use + our Site are generally limited to service providers who only use any information + collected to provide services for us and not to provide services or advertising for + any other party. Note, however, that we also provide certain widgets or tools on our + sites that allow you to interact with third parties who provide these features, such + as tools that allow web surfers to easily share information on another platform. At + other times, information from a third party may be embedded on our Site, such as a + map. These widgets, tools, and informational items often function through the use of + third-party cookies utilized by the third party site. As a result, these third + parties may have access to information about your web browsing on the pages of our + Site where these widgets, tools, or information are placed. You may wish to review + information at third party sites, where you have an account, to determine how these + third parties treat data that they obtain through the use of cookies. +

+
+
+ +
+

III. Do You Have to Accept Cookies?

+ +

+ You may be able to set your browser to reject cookies. If you set your browser + options to disallow cookies, you may limit the functionality we can provide when you + visit our Site. The latest versions of internet browsers provide cookie management + tools, such as the ability to delete or reject cookies. We recommend that you refer + to information supplied by browser providers for more specific information, + including how to use these tools. +

+
+
+ +
+

IV. Additional Technologies

+

+ We do not typically use additional technologies such as pixel tags, web beacons, and + clear GIFs. We permit third-party service providers to use these technologies. They + use these technologies for purposes such as determining viewing and response rates. +

+
+
+ +
+

V. Using Information

+

+ In addition to the uses described above, we may use information for purposes as + allowed by law such as: servicing; communicating with you; improving our Site, + products, or services; legal compliance; risk control; information security; + anti-fraud purposes; tracking website usage, such as number of hits, pages visited, + and the length of user sessions in order to evaluate the usefulness of our sites. +

+
+
+ +
+

VI. Sharing

+

+ We share information with service providers with whom we work, such as service + providers and companies that help us service you better. When permitted or required + by law, we may share information with additional third parties for purposes + including response to legal process. As applicable, please see our{' '} + Privacy policy for more information on how we may + share information with affiliates and third parties. +

+
+
+
+
+
+ ) +} diff --git a/apps/beets-frontend-v3/app/(marketing)/layout.tsx b/apps/beets-frontend-v3/app/(marketing)/layout.tsx new file mode 100644 index 000000000..adb44aa12 --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/layout.tsx @@ -0,0 +1,16 @@ +/* eslint-disable max-len */ +import { getProjectConfig } from '@repo/lib/config/getProjectConfig' +import { Box } from '@chakra-ui/react' +import { Metadata } from 'next' +import { PropsWithChildren } from 'react' + +const { projectName } = getProjectConfig() + +export const metadata: Metadata = { + title: `${projectName} DeFi AMMs made easy`, + description: `DeFi's most extensive AMM product suite—Balancer is a decentralized Automated Market Maker protocol built on Ethereum with a clear focus on fungible and yield-bearing liquidity.`, +} + +export default function MarketingLayout({ children }: PropsWithChildren) { + return {children} +} diff --git a/apps/beets-frontend-v3/app/(marketing)/page.tsx b/apps/beets-frontend-v3/app/(marketing)/page.tsx new file mode 100644 index 000000000..811cab94a --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/page.tsx @@ -0,0 +1,25 @@ +'use client' + +import { ReactLenis } from '@studio-freight/react-lenis' +import { Box } from '@chakra-ui/react' +import { AnimatedSVG } from '@repo/lib/shared/components/marketing/AnimatedSVG' +import { HomeHero } from '@repo/lib/shared/components/marketing/HomeHero' +import { HomeBuilders } from '@repo/lib/shared/components/marketing/HomeBuilders' +import { HomeProtocols } from '@repo/lib/shared/components/marketing/HomeProtocols' +import { HomeActivity } from '@repo/lib/shared/components/marketing/HomeActivity' + +export default function Home() { + return ( + + + + + + + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/(marketing)/privacy-policy/page.tsx b/apps/beets-frontend-v3/app/(marketing)/privacy-policy/page.tsx new file mode 100644 index 000000000..ee1728b05 --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/privacy-policy/page.tsx @@ -0,0 +1,426 @@ +'use client' + +import Link from 'next/link' +import { Container } from '@chakra-ui/react' +import { Prose } from '@nikolovlazar/chakra-ui-prose' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' + +export default function Privacy() { + return ( + + +
+ +
+

Balancer Privacy Policy

+

+ Last Updated: October 2023 +

+

+ + This Privacy Policy explains how the Balancer Foundation, its subsidiary, Balancer + OpCo Limited (“Balancer Foundation,” “Balancer,” “we,” “our,” or “us”) collects, + uses, and discloses information about you. This Privacy Policy applies when you + use our website, Balancer Protocol user-interface or application and other online + products (collectively, our “UI”), engage with us on social media, or otherwise + interact with us. + +

+

+ + We may change this Privacy Policy from time to time. If we make changes, we will + notify you by revising the date at the top of this policy and, when material, we + will provide you with additional notice by adding a statement to our website and + consent as required under applicable law. Your continued use of this UI after we + make changes is deemed to be acceptance of those changes when permissible. We + encourage you to review this Privacy Policy regularly to stay informed about our + information practices and the choices available to you. + +

+
+
+ +
+

Summary

+
    +
  • + Balancer does not typically request, collect or use personal information. With the + exception of your wallet address, there is no reason for you to provide personal + information when you use the UI. +
  • +
  • + Balancer does not and has not stored personal information from users of the UI. + However, Balancer uses third party services including, without limitation, + Cloudflare, Fathom Analytics, Appzi and others who collect and store certain user + information only for use in the provision of their services. +
  • +
  • + Balancer does not set any cookies. However, we use third party service providers + that set cookies. +
  • +
+
+
+ +
+

Collection of Information

+

Information You Provide to Us

+ +

+ We do not typically request, collect or use personal information from you except + under limited circumstances as described herein. With the exception of your wallet + address, there is no reason for you to provide personal information when you use the + UI. Your use of the UI will not be customized and this policy reflects that + practice. +

+

+ Balancer is not directed to children under the age of 16. If a parent or guardian + becomes aware that his or her child has provided us with personal information + without your consent, please contact us at + + privacypolicy@balancer.finance + + . If we become aware that a child under the age of 16 has provided us with personal + information, we will take reasonable efforts to delete such personal information. +

+ +

Information We Collect Automatically When You Interact With Us

+

+ When you access or use our UI, we may automatically collect certain information, + including: +

+
    +
  • + Device and Usage Information: We (and our + service providers) collect information about how you access the UI, including data + about the device and network you use, such as your hardware model, operating + system version, mobile network, browser type, IP address and app version. We do + not typically, but we may, also collect information about your activity on the UI, + such as access times, pages viewed, links clicked, and the page you visited before + navigating to the UI. +
  • +
  • + + Information Collected by Cookies and Similar Tracking Technologies: + + We do not typically use tracking technologies, such as cookies and web beacons, to + collect information about you; however, third parties we rely on may do so. + Cookies are small data files stored on your hard drive or in device memory that + help us improve the UI and your experience, see which areas and features of the UI + are popular, and count visits. Web beacons (also known as “pixel tags” or “clear + GIFs”) are electronic images that we use on the UI to help deliver cookies, count + visits, and understand usage and campaign effectiveness. For more information + about cookies and how to disable them, see our{' '} + Cookies policy and the Your Choices section + below. +
  • +
+ +

Information We Collect from Other Sources

+ +

+ We do not typically obtain information from third-party sources in order to provide + business services. We do not sell information we collect. +

+ +

Information We Derive

+ +

+ We may derive limited information or draw inferences about you based on the + information we have access to or receive, most importantly, from our service + providers. Your wallet and IP address is accessible to Balancer and its vendor(s). + We may make inferences about you based on your wallet or IP address. +

+
+
+ +
+

Use of Information

+ +

+ We do not collect your personal information, other than wallet address, to customize + the UI for your use. However, we reserve the ability to use information we collect + to provide, maintain, administer and/or improve the UI. We may also use the + information we collect to: +

+
    +
  • Ensure proper functioning of Balancer and the UI;
  • +
  • Provide services, content, material and other information on the UI;
  • +
  • Identify and/or diagnose problems on or related to the UI;
  • +
  • + Send technical notices, security alerts, and support and administrative messages; +
  • +
  • + Provide requested information, technical support and/or integrations such as an + application programming interface or API; +
  • +
  • Respond to comments and questions;
  • +
  • Analyze trends, usage, and activities in connection with the UI;
  • +
  • + Detect, investigate, and prevent security incidents and other malicious, + deceptive, fraudulent, or illegal activity and protect the rights and property of + Balancer and others; +
  • +
  • Debug to identify and repair errors in the UI;
  • +
  • Comply with legal, regulatory and financial obligations;
  • +
  • + Carry out any other purpose described to you at the time the information was + collected; and +
  • +
  • + For other reasonable internal use or uses aligned with your relationship with us + and the context in which we collected the information. +
  • +
+
+
+ +
+

Sharing of Information

+ +

+ We do not have access to or share personally identifiable information, other than as + described herein, in the normal course of Balancer business. However, when Balancer + has access to personal information, such as your wallet and certain IP addresses, it + may share that information in the following circumstances or as otherwise described + in this policy: +

+
    +
  • + We share personal information with vendors, service providers, and consultants + that need access to personal information in order to perform services for us, such + as transaction monitoring, data management, fraud prevention, customer service and + support, marketing and/or advertising. +
  • +
  • + If you choose to use integrations, we may share certain information with the + integration partners. +
  • +
  • + We may disclose personal information if we believe that disclosure is in + accordance with, or required by, any applicable law or legal process, including + lawful requests by public authorities to meet national security or law enforcement + requirements. +
  • +
  • + We may share personal information if we believe that your actions are inconsistent + with our user agreements or policies, if we believe that you have violated the + law, or if we believe it is necessary to protect the rights, property, and safety + of Balancer, the Balancer ecosystem, the public, or others. +
  • +
  • + We share personal information with our lawyers and other professional advisors + where necessary to obtain advice or otherwise protect and manage our business + interests. +
  • +
  • + We may share personal information in connection with, or during negotiations + concerning, merger, sale of company assets, financing, bankruptcy, business + closure, or acquisition of all or a portion of our assets. Additionally, as part + of such an event, we may transfer or sell personal information to a third party. + We will provide notice to you on our UI of any such sharing to a third party and + any choices you may have regarding the sharing of your personal information. +
  • +
  • + Personal information may be shared between and among Balancer and our current and + future parents, affiliates, and subsidiaries and other companies under common + control and ownership (“corporate affiliates”). This information may be used to + provide you with offers, services, or products that may be of interest to you and + provide you with their products and services. Any such corporate affiliate may use + your personal information only according to the terms of this Policy. If you are + located in a jurisdiction where such sharing requires your permission, we will + only share such information with your consent. If you decide you no longer wish to + receive these promotional communications, please follow the instructions provided + in Your Choices section below. +
  • +
  • We share personal information with your consent or at your direction.
  • +
  • + We also share aggregated or de-identified information that cannot reasonably be + used to identify you. +
  • +
+
+
+ +
+

Advertising and Analytics

+ +

+ We do not work with third parties to serve ads to you as part of customized + campaigns on the UI or third-party UIs. +

+
+
+ +
+

Transfer of information to the United States and Other Countries

+ +

+ Balancer Foundation is headquartered in the Cayman Islands with a subsidiary in the + British Virgin Islands (BVI). Therefore, we and our service providers may transfer + your personal information to, or store or access it in, jurisdictions that may not + provide levels of data protection that are equivalent to those of your home + jurisdiction. We will take steps to ensure that your personal information receives + an adequate level of protection in the jurisdictions in which we process it. +

+
+
+ +
+

Your Choices

+

Cookies

+

+ Balancer and its third party vendors may use any cookies to affect the availability + and functionality of the UI. For more information about cookies and how to disable + them, see our Cookies policy. +

+
+
+ +
+

Additional Considerations

+ +

+ In the preceding 12 months, we or our vendors may have collected the following + categories of personal information: identifiers, internet or other electronic + network activity information and inferences. For details about the data points we + collect and the categories of sources of such collection, please see the Collection + of Information section above. We collect personal information for the purposes + described in the Use of Information section above. In the preceding 12 months, we + have disclosed the following categories of personal information for business + purposes to the following categories of recipients: +

+ + + + + + + + + + + + + + +
Category of Personal InformationType of Information & Categories of Recipients
Identifiers +

+ We share with vendors, such CloudFlare and Fathom Analytics: certain IP + addresses, device identifiers or other similar identifiers. +

+ +

+ With our compliance partner, TRM Labs, we only share wallet addresses used to + connect a wallet to our UI (all other user information like IP addresses, + device identifiers and location are not shared). The code for the UI is open + source, and can be reviewed by anyone at any time. +

+
Internet or other electronic network activity information + We share with vendors: information regarding an interaction with an UI/website +
+ +

+ Balancer does not “sell” personal information to advertise our products to you or + otherwise. +

+ +

+ Subject to certain limitations, you have the right to (1) request to know more about + the categories and specific pieces of personal information we collect, use, and + disclose, and sell, (2) request deletion of your personal information, (3) opt out + of any “sales” of your personal information that may be occurring, and (4) not be + discriminated against for exercising these rights. You may make these requests by + emailing us at + + privacypolicy@balancer.finance + + . If we receive your request from an authorized agent, we may ask for evidence that + you have provided such agent with a power of attorney or that the agent otherwise + has valid written authority to submit requests to exercise rights on your behalf. If + you are an authorized agent seeking to make a request, please contact us. +

+ +

Shine the Light

+ +

+ Balancer does not share such information with third parties for direct marketing + purposes. +

+ +

Do Not Track Signals

+ +

+ Our Services do not respond to “Do Not Track” signals communicated by your browser. + We do not knowingly retain or sell tracking information collected about your online + activity. For more information about Do Not Track, please visit{' '} + + www.allaboutdnt.com + + . +

+
+
+ +
+

Additional Disclousures for Individuals in Europe

+ +

+ If you are located in the European Economic Area (EEA), the United Kingdom, or + Switzerland, you have certain rights and protections under the law regarding the + processing of your personal data, and this section applies to you. +

+

Legal Basis for Processing

+ +

+ Balancer does not typically process user personal data. If Balancer processes data, + such as a wallet address and certain IP addresses, it will do so in reliance on the + following lawful bases: +

+
    +
  • + To perform our responsibilities under our contract with you (e.g., providing + access to the UI you requested). +
  • +
  • + When we have a legitimate interest in processing your personal data to operate the + UI or protect our interests (e.g., to adhere with applicable laws, rules and + regulations, provide, maintain, and improve our products and UI, conduct data + analytics, and communicate with you). +
  • +
  • To comply with our legal obligations.
  • +
+

Data Retention

+ +

+ We do not maintain customer accounts or store personal data. Our vendor will store + your wallet address in order to provide requested services. +

+

Data Subject Requests

+

+ Subject to certain limitations, you have the right to request access to the personal + data we hold about you and to receive your data in a portable format, the right to + ask that your personal data be corrected or erased, and the right to object to, or + request that we restrict, certain processing. Balancer does not typically hold or + store such personal data. +

+
+
+ +
+

Contact Us

+ +

+ If you have any questions about this Privacy Policy, please contact us at{' '} + + privacypolicy@balancer.finance + + . +

+
+
+
+
+
+ ) +} diff --git a/apps/beets-frontend-v3/app/(marketing)/risks/page.tsx b/apps/beets-frontend-v3/app/(marketing)/risks/page.tsx new file mode 100644 index 000000000..a4f17f2fe --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/risks/page.tsx @@ -0,0 +1,1321 @@ +'use client' + +import Link from 'next/link' +import { Container, Divider, Box } from '@chakra-ui/react' +import { Prose } from '@nikolovlazar/chakra-ui-prose' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' + +export default function Privacy() { + return ( + + +
+ + +

Risks of using Balancer

+

+ Last Updated: May 2024 +

+

+ + There are many inherent risks developers accept when working in DeFi and using the + Balancer Protocol. This page aims to summarize the top risks to help you with your + risk decisions. It is important to note that this list is not exhaustive, and + there may be additional risks not explicitly mentioned here. As the risk + environment is fluid, we expect to periodically update this summary. + +

+
+
+ + +
+ +
+
+ +
+

Risks for Liquidity Providers (LPs)

+

+ General risks +

+

+ Smart contract risk +

+

+ Smart contract risk is a general risk when using DeFi protocols, including Balancer. + Smart contracts are self-executing pieces of code that run on certain blockchains, + like Ethereum. Although they are designed to be secure, they can be vulnerable to + bugs and exploits. +

+

+ If there is a flaw in the smart contract code, it can be exploited by attackers to + steal funds from the protocol. This can result in the loss of funds for liquidity + providers and swappers who are using the protocol. Smart contract risk is a major + risk for all DeFi users, and it is important to carefully evaluate the security of + the protocols before using them. +

+
The Balancer Vault
+

+ The main architectural change between Balancer V1 and Balancer V2 is the transition + to a single vault that holds and manages all the assets added by all Balancer + pools. This separates the AMM logic from the token management and accounting. Token + management/accounting is done by the vault while the AMM logic is individual to each + pool. This provides many advantages, including flexibility and gas efficiency. +

+

+ One critique of this approach is that the Balancer Vault could be a single point of + failure—i.e. hack the vault, get all the tokens of the protocol. This Balancer Vault + architecture was heavily audited prior to launch and has now been battle-tested + since May 2021, securing over $3b. It has also been forked by other teams across + different networks, including Beethoven X on Fantom, without issue. +

+
How does Balancer work to mitigate this risk?
+
    +
  • + Development teams have engaged with top tier smart contract auditing firms to + identify and fix bugs before deployment. +
  • +
  • + The core of Balancer smart contracts are immutable and do not use proxies or other + upgrade mechanisms. Note: Within DeFI, upgradable contracts are a major way + exploits have been introduced. +
  • +
  • + In addition, Balancer has a bug bounty program via{' '} + Immunefi to attract white-hat + hackers to responsibly disclose any bugs. Rewards are distributed based on threat + level—for critical smart contract vulnerabilities, there is a minimum reward of + 250 ETH and a maximum reward of 1,000 ETH. +
  • +
+
How can LPs mitigate this risk?
+
    +
  • + LPs should carefully research and use DeFi protocols that are battle-tested with a + history of functioning as intended, while securing large amounts of assets. +
  • +
  • + To diversify risk, LPs may consider not placing all their tokens into a single + protocol. +
  • +
+
+
+ +
+

Mechanism / Economic risk

+

+ An mechanism or economic exploit of a DeFi protocol occurs when an attacker is able + to manipulate the economic incentives of the protocol to their advantage, resulting + in a loss of funds for other participants. This can happen even when there are no + smart contract bugs or other unintended logic errors. +

+

+ For example, an attacker could take advantage of a liquidity pool's pricing + mechanism to intentionally cause the price of an asset to deviate from its true + value, allowing them to buy or sell that asset at a profit. +

+

+ In addition, the composable nature of DeFi means that a pool on Balancer may contain + tokens that may be manipulated by an attacker on a third party protocol, which + further increases risk. +

+

These types of economic exploits are difficult to detect and prevent.

+
How does Balancer work to mitigate this risk?
+
    +
  • + Balancer strives to deliver careful economic modeling, rigorous mechanism design, + testing and audits by top tier auditing firms. +
  • +
+
How can LPs mitigate this risk?
+
    +
  • + LPs should carefully research and use DeFi platforms that are battle-tested with a + history of functioning as intended, while securing large amounts of assets. +
  • +
+
+
+ +
+

Toxic pool token risk

+

+ A liquidity pool is only as good as its weakest token. This is because liquidity + pools typically sell the winners (tokens moving up in price) and accumulate the + losers (tokens moving down in price). If a pool contains a toxic token, the value of + the BPT (LP tokens) of the liquidity pool could go to zero. This is the case even if + the other pool tokens remain good and would otherwise not be affected. +

+

+ A toxic token could be seeded into a liquidity pool by a malicious pool creator or + an otherwise good token could become toxic (similar to Terra’s stablecoin{' '} + UST). +

+
Tokens that could become problematic for LPs:
+ +
    +
  • + Unsupported tokens on Balancer Protocol, including: +
      +
    • + + Rebasing tokens + +
    • +
    • Tokens with transfer fees
    • +
    • Proxy tokens with double entry points
    • +
    • Tokens with more than 18 decimal points
    • +
    • Rebasing tokens
    • +
    +
  • + +
  • + Tokens that become toxic, including: +
      +
    • Tokens that are infinitely minted
    • +
    • Tokens that become frozen or exploited in any other way
    • +
    • Stablecoins that lose their peg
    • +
    +
  • +
+
+ Rebasing tokens +
+

+ Rebasing tokens are a type of cryptocurrency that adjusts the supply of the token + based on a predetermined formula. This formula is usually designed to keep the price + of the token stable relative to some external metric, such as the price of a + particular asset or a specific index. When the external metric changes, the token + supply is adjusted, which in turn affects the price of the token. +

+

+ For example, if a rebasing token is designed to maintain a price of $1 per token and + the price of the external asset goes up by 10%, the token supply would decrease by + 10% to maintain the $1 price point. Similarly, if the external asset price goes down + by 10%, the token supply would increase by 10%. +

+

+ Some examples of rebasing tokens include stETH and + AMPL. +

+

+ Unfortunately, rebasing tokens generally don’t work well in liquidity pools + since LPs may suffer losses when rebasing occurs. +

+ +
How does Balancer mitigate these risks?
+
    +
  • + Since the Balancer protocol is permissionless, anyone can create a liquidity pool + composed of any ERC-20 token. This makes this type of risk difficult to mitigate. +
  • +
  • + The Balancer App UI may be updated to exclude blacklisted tokens and pools but LPs + should not rely on this. +
  • +
  • + Instead of including tokens which rebase, new DeFi liquidity pool compatible + wrapped tokens which do not rebase may be utilized. An example of this is{' '} + wstETH + —a wrapped token which includes the accumulated yield from Lido ETH staking and + does not rebase like + stETH. +
  • +
  • + For Balancer Managed Pools, a novel feature called ‘circuit breakers’ + has been designed to halt swapping if there is a large, uncorrelated drop in a + token’s value. +
  • +
  • + New pools have a ‘recovery mode’ which can be enabled by the Emergency + DAO Multisig. Pools in recovery mode provide a simple way for LPs to exit the pool + proportionally at the cost of disabling protocol fees (swaps, joins etc still + work). +
  • +
+ +
How can LPs mitigate these risks?
+
    +
  • + LPs should carefully check each pool constituent token and understand its specific + risks. +
  • +
  • + LP’s should review all pool tokens before providing liquidity to ensure no + constituent pool tokens are unsupported by the Balancer Protocol (e.g. rebasing + tokens). +
  • +
  • + LPs should carefully check the pool creator address to verify it’s from a + reliable actor. +
  • +
+
+
+ +
+

+ DeFi composability risks +

+

+ DeFi composability refers to the ability of different DeFi protocols and + applications to work together seamlessly in endless combinations, allowing + developers to create more complex financial transactions and applications. This is + sometimes referred to as DeFi lego building blocks, since they can be combined and + connected to created interesting new structures and applications. +

+

+ While composability offers many benefits, layering on protocols and applications on + top of each other comes with additional risks. For example, risks get compounded + when multiple protocols are composed together, as a vulnerability in one contract + could impact others. The interconnectivity of DeFi protocols can amplify risks, + turning isolated incidents into systemic threats. For example, if a major protocol + fails or suffers from an exploit, it could lead to a domino effect, impacting other + protocols and users in the ecosystem. +

+

+ Other risks could cascade if a protocol within a composability stack has a liquidity + crisis, an unfavorable governance decision or regulatory outcome. +

+
+
+ +
+

+ DAO Governance risk +

+

+ Balancer currently uses off-chain voting mechanisms to signal the will of veBAL + token holders (vote-escrow BAL). This off-chain voting is done via{' '} + Snapshot + —originally developed in-house by Balancer Labs. +

+

A summary of the immutability of the Balancer Protocol’s smart contracts:

+
    +
  • + Balancer V1 contracts are immutable, so there were no core protocol parameters + that could be changed. +
  • +
  • + Balancer V2 contracts do allow for some tweaking of core protocol parameters, + including the ability to: +
      +
    • + Set a share of swap fees to be diverted to the protocol (hard capped at 50% of + the swap fee) +
    • +
    • Set a Flash Loan fee
    • +
    • + Extract from the vault collected protocol fees and/or excess balances (e.g. + airdrops), to any destination +
    • +
    • Set the address of the oracle implementation
    • +
    • + Set relayer addresses: relayers are (user opt-in, audited) contracts that can + make calls to the vault (with the transaction “sender” being any arbitrary + address) and use the sender’s ERC20 vault allowance, internal balance or + BPTs on their behalf +
    • +
    • + Set dynamic-fee controllers: addresses (initially assigned to Gauntlet) that + may change the swap fee for pools created by the dynamic-fee pool factory that + will be deployed by Balancer Labs +
    • +
    • Add and remove veBAL gauges
    • +
    +
  • +
+

+ Note: The system of Balancer Governance may change in the future. For example, + Balancer community members have expressed interest in moving from the Multisig + towards on-chain governance execution by veBAL token holders. +

+

+ The main risk with this setup consisting of off-chain voting executed by MultiSigs: +

+
    +
  • + The{' '} + + Multisig signer set + {' '} + could go rogue and disregard the decision made by veBAL holders in the off-chain + voting. +
  • +
  • + The{' '} + + Multisig signer set + {' '} + could mistakenly execute the wrong instruction without malice. +
  • +
  • + An individual or an entity could acquire substantial veBAL and vote against the + interests of the majority of the community. +
  • +
+
How Balancer aims to mitigate this risk:
+
    +
  • + The core of Balancer smart contracts are immutable and do not use proxies or other + upgrade mechanisms. Only parameters, which are considered to be less + ‘dangerous’ may be tweaked. +
  • +
  • + The Multisig does not have custody of, nor control over, funds from + liquidity providers locked inside Balancer Protocol contracts. Balancer V2 was + designed so that even if a multisig goes rogue, all the liquidity is safe and can + be withdrawn by their rightful owners. +
  • +
+
How LPs can mitigate this risk:
+
    +
  • + LPs should stay up to date with Balancer Governance by following discussions on + the forum and participating in the off-chain voting. +
  • +
  • + LPs may review past votes and verify that the DAO Multisig has executed outcomes + accurately. +
  • +
+
+
+ +
+

+ Flash Loans risk +

+

+ A Flash Loan is a type of loan where a user borrows assets with no upfront + collateral and returns the borrowed assets within the same blockchain transaction. + Flash Loans use smart contracts which requires that a borrower repays the loan + before the transaction ends. They are typically used for arbitrage opportunities, + collateral swaps and to lower transaction fees, across potentially multiple + protocols. It’s a powerful new financial primitive, native to DeFi. +

+

Flash Loans may be used on Balancer and interact with the Balancer Vault.

+

+ While Flash Loans offer many benefits, they also comes with certain risks. Flash + Loans have also been used for multiple DeFi exploits resulting in losses worth + millions of dollars. Flash Loan exploits are relatively new with the full range of + attack surfaces still being discovered. +

+
How Balancer aims to mitigate this risk:
+
    +
  • The Balancer Vault is non-reentrant, which blocks most Flash Loan attacks.
  • +
  • + Balancer strives to deliver careful economic modeling, rigorous mechanism design, + testing and audits by top tier auditing firms. +
  • +
+
+
+ +
+

+ Mutable pool attributes +

+

+ Balancer is a flexible AMM that allows people to create different types of liquidity + pools, including those with immutable and/or mutable pool attributes. +

+

+ For pools with immutable attributes, LPs can be assured that the rules are designed + so they cannot change once they have provided liquidity since no pool attribute + should be changed by anyone at any time. +

+

For pools with mutable attributes, LPs should understand:

+
    +
  • + Which attributes can change +
      +
    • + Certain attributes being mutable provide more risk than others. For example, + changing the swap fee percentage is generally viewed as less risky than the + ability to change the constituent tokens of a pool, since a malicious editor + could introduce a toxic pool token. +
    • +
    +
  • +
  • + Who can change each attribute +
      +
    • + On Balancer pools, if an attribute is editable, the address that can make the + edit is also specified. The two most common parties that are set to be able to + change pool attributes are either the Pool Owner or Balancer Governance. +
    • +
    +
  • +
+
How does Balancer work to mitigate this risk?
+
    +
  • + For known pool types, the Balancer App UI transparently displays pool attributes + and specifies if it is editable and if so, by whom. +
  • +
  • + Balancer Managed Pools are designed to have mutable attributes that can be changed + by the Pool Owner. For certain ‘dangerous operations’, there are + ‘timelock delays’ which give LPs a period to review the proposed + changes and withdraw funds if they do not agree with the change. In addition, Pool + Controllers can set a guardian who has the ability to veto a proposed change from + the Pool Owner if they believe it to be a malicious change or a mistake. +
  • +
+
How can LPs mitigate this risk?
+
    +
  • + LPs should check to see the edibility of pool attributes and understand who can + authorize any changes. +
  • +
+
+
+ +
+

+ Loss of funds on join/exit of a pool +

+
Due to high price impact
+

+ When joining a pool, LPs should be aware of the price impact from adding tokens to + the pool. In general, adding liquidity in proportional amounts to the token weights + of the pool incur low price impact. Adding custom token amounts (non-proportionally) + causes the internal prices of the pool to change, as if you were swapping tokens. + The higher the price impact the more you'll spend in swap fees. +

+
Due to slippage
+

+ LPs should also consider the effect of slippage when adding liquidity to a pool. + Slippage occurs when market conditions change between the time your order is + submitted and the time it gets executed on Ethereum. Slippage tolerance is the + maximum change in price you are willing to accept. +

+

+ Slippage tolerance is a setting in both the Add/Remove liquidity flows on the + Balancer App UI. Setting a low slippage tolerance protects you from front-running + bots and miner extractable value (MEV). +

+
Due to high Gas fees
+

+ Gas on the Ethereum network refers to the unit that measures the amount of + computational effort required to execute specific operations. Gas fees in Ethereum + are the transaction costs users pay to have their transactions processed and + validated by the network's miners. Gas fees vary depending on network + congestion, transaction complexity, and the amount of gas a user is willing to pay. +

+

+ Gas fees can be particularly high during periods of network congestion. As a result, + LPs might face increased costs when adding or removing liquidity, making adjustments + to their positions, or claiming liquidity mining incentives. If the gas fees are + higher than the returns they get from providing liquidity, LPs may end up with a net + loss. +

+
How Balancer aims to mitigate this risk:
+
    +
  • + The Balancer Smart Order router is used to route liquidity efficiently via pools + to minimize price impact. +
  • +
  • The Balancer App UI gives LP’s control over their slippage settings.
  • +
  • + LP’s are warned via the Balancer App UI when the price impact is excessive. + Once price impact exceeds a certain threshold, the Balancer App UI prevents + user’s from executing a transaction where they would otherwise get rekt. +
  • +
+
How LP’s can mitigate this risk:
+
    +
  • + Users should review their slippage settings and potential price impact before + adding or removing liquidity. +
  • +
  • + Users should also review gas prices and the potential gas fee before any + transaction. This information is usually provided by their wallet provider. +
  • +
+
+
+ +
+

+ Impermanent loss +

+

+ Impermanent loss is a risk that liquidity providers (LPs) face when providing + liquidity to an automated market maker (AMM) like Balancer. It is the difference + between the value of holding assets in a pool versus holding them outside of the + pool. +

+

+ If the price of the assets in the pool changes, LPs may experience a loss compared + to holding the assets outside of the pool. This can happen because the AMM algorithm + rebalances the pool to maintain a constant ratio of the assets in the pool. If the + price of one asset increases, the algorithm will sell some of that asset and buy + more of the other asset to maintain the ratio. This means that LPs will sell the + asset that is increasing in price and buy the asset that is decreasing in price, + resulting in a loss. +

+

+ This risk is particularly relevant for pools with volatile assets where token prices + are likely diverge over time. +

+
How does Balancer work to mitigate this risk?
+
    +
  • + All AMMs either have impermanent loss or reduced yield to LPs. Balancer aims to + make its pools as capital efficient as possible so that the yield LPs make is more + likely to exceed any impermanent loss. +
  • +
  • + The Balancer protocol supports unbalanced pools which LPs can use to reduce + impermanent loss. For example, there is lower impermanent loss in an 80/20 pool + (or any other unbalanced pools) versus a 50/50 pool with the same underlying + tokens. +
  • +
  • + Note: Some ecosystem developers are building on top of Balancer to create novel + pools, including Managed Pools, with rebalancing algorithms designed to minimize + impermanent loss. +
  • +
+
How can LPs mitigate this risk?
+
    +
  • + LPs should consider the risk of impermanent risk carefully before providing + liquidity to a Balancer pool. +
  • +
  • + The longer an LP holds their position, the more likely it is that their yield from + swap fees offset and exceed any impermanent loss, assuming the price divergence of + the token prices isn’t extreme. +
  • +
  • + LPs may consider providing liquidity into pools with less likelihood of token + price divergence. For example, stable pools or boosted pools. +
  • +
  • + LP’s should consider providing liquidity in unbalanced pools, like 80/20 + pools which result in less impermanent loss versus a 50/50 pool with the same + underlying tokens. +
  • +
+
+
+ +
+

+ User Interface (UI) risk +

+

+ DeFi users, including liquidity providers and swappers, typically interact with + front-end user interfaces to interact with a protocol’s smart contracts. An + example is the app.balancer.fi front-end UI instance which interacts with Balancer + Protocol smart contracts. +

+ +

A few risks of using front-ends to manage liquidity positions in DeFi:

+
    +
  • + UIs may not always display timely, accurate data. This may be due to the use of + third party data services experiencing periods of downtime or network congestion. +
  • +
  • UIs could be maliciously updated or exploited by rogue developers.
  • +
  • UIs may be updated and remove certain feature sets.
  • +
  • + UIs may block certain wallet addresses or user’s in certain jurisdictions to + comply with their regulations. +
  • +
  • + UIs may experience periods of downtime or potentially be discontinued. UIs may + also be shut down or have access denied to users in certain jurisdictions. +
  • +
+ +
How does Balancer work to mitigate this risk?
+
    +
  • + Since the Balancer smart contracts can be interacted with by any front-end UI, + there is less reliance on any one single UI. The Balancer App UI code is open + source with an MIT License which allow other third party developers to fork the + code, make improvements and compete for users. +
  • +
  • + Users or third party developers can keep track of changes and review the open + source repository on the Balancer Github for potential malicious code. +
  • +
  • + The developers of the Balancer App UI have provided instructions on how to clone + and run local environments of the app. This allows people to have the ability to + keep deprecated features or modify the code to add new features that they prefer. +
  • +
+
How can LPs mitigate this risk?
+
    +
  • + LP’s can learn how to interact with Balancer smart contracts on third party + websites, like Etherscan. +
  • +
  • + To mitigate the risks of downtime or lack of access, users can fork the open + source code and run their own local instance. +
  • +
+
+
+ +
+ {' '} +

+ Regulatory risk +

+

+ The regulatory frameworks applicable to blockchain transactions in connection with + tokens and stablecoins are still developing and evolving. In addition, the + increasing complexity of DeFi applications and their interactions can make it + difficult to assess and regulate them effectively. This could potentially lead to + increased regulatory scrutiny or even a regulatory crackdown, which could have + negative consequences for participants, our efforts to mitigate risks and the entire + DeFi ecosystem. +

+

+ It's also possible that the Balancer App UI may be wholly or partially + suspended or terminated for any or no reason, which may limit your access to your + tokens via this website. In this scenario, you may be able to recover funds by + forking the open-source code on{' '} + Github and running your own + local instance, or by using a third party website, like{' '} + Etherscan. +

+
+ + + +
+ {' '} +

+ Pool type risks +

+

+ Balancer is designed to be infinitely extendible to allow for any conceivable + pool type with custom curves, logic and parameters, and more. The general risks + of the most popular pool types are listed below. +

+
+
+ +
+

+ Weighted Pools +

+

+ Weighted Pools use{' '} + + Weighted math + + , which makes them great for general cases, including tokens that don't + necessarily have any price correlation (ex. DAI/WETH). Unlike weighted pools in + other AMMs that only provide 50/50 weightings, Balancer Weighted Pools enable + users to build pools with more than two tokens and custom weightings, such as + pools with 80/20 or 60/20/20 weightings. Some risks of weighted pools include: +

+
    +
  • + Impermanent loss on volatile non-correlated assets +
      +
    • See above for details of impermanent loss risks.
    • +
    +
  • +
  • + Toxic token risk +
      +
    • + Balancer weighted pools are not limited to just having two tokens. The + more tokens in a pool, the more risk that one of these could become toxic. +
    • +
    +
  • +
+
+
+ +
+

+ Stable Pools +

+
Loss of stablecoin peg
+

+ Stablecoins are tokens whose value is intended to be pegged or tied to that of + another asset, which could be a currency, commodity or financial instrument. + There are many types of stablecoins, some are risky than others depending on + product design including evidence of reserves to support the peg in times of + stress. Some example types of stablecoins include: +

+
    +
  • + Peg is secured by real world reserves +
      +
    • e.g. USDC secured by USD reserves
    • +
    +
  • +
  • + Peg is secured by other crypto assets +
      +
    • e.g. DAI secured by an over-collateralized basket of crypto assets
    • +
    +
  • +
  • + Peg is secured by smart contract algorithms +
      +
    • + e.g. UST which aimed to be secured by algorithmic rebalances to reflect + the peg. +
    • +
    +
  • +
+

+ Depegging occurs when a stablecoin losses its peg to the target asset. In stable + pools, if a stablecoin depegs, LPs may incurs losses. This is because liquidity + pools typically sell the winners (tokens moving up in price) and accumulate the + losers (tokens moving down in price). In the case of a USD-pegged stable pool, + if an asset permanently loses it’s peg to $1 and goes down in value, the + pool will sell any pegged assets and accumulate the asset which has lost + it’s peg, leading to an overall loss of funds for LPs. +

+
+
+ +
+

+ Composable Stable Pools & MetaStable Pools +

+

+ Composable Stable Pools are designed for assets that are either expected to + consistently trade at near parity, or at a known exchange rate. Composable + Stable Pools use Stable Math (based on StableSwap, popularized by Curve) which + allows for trades of significant size before encountering substantial price + impact, vastly increasing capital efficiency for like-kind and correlated-kind + swaps. They are ideal for: +

+
    +
  • + Pegged Tokens: Tokens that trade near 1:1, such as two stablecoins of the same + currency (eg: DAI, USDC, USDT), or synthetic assets (eg: renBTC, sBTC, WBTC) +
  • +
  • + Correlated Tokens: Tokens that trade near each other with some slowly changing + exchange rate, like derivatives (eg: wstETH, wETH) +
  • +
+

+ Note: Composable Stable Pools are a superset of all previous Stable-type pools + (Stable Pools, MetaStable Pools, StablePhantom Pools, and StablePool v2) and + therefore obsolete all previous pools. +

+

+ Composable Stable Pools (including MetaStable Pools) carry the all of the same + risks as stable pools, including the potential depegging of constituent + stablecoin tokens. In addition, there are risks associated with the involvement + of rate providers. +

+
+
+ Rate provider risk +
+

+ Rate Providers are contracts that provide an exchange rate between two assets. + These exchange rates can come from any on-chain source, whether that may be an + oracle, a ratio of queryable balances, or another calculation. +

+

+ This introduces risks around the rate provider being able to supply accurate + and timely exchange rates between pool tokens. +

+
+ +
+
Oracle risk
+

+ Oracles are data providers which supply external information to smart + contracts. Oracles, like Chainlink, may be used to source exchange rates + between pool tokens for a rate provider in Balancer MetaStable pools. The + risks of using Oracles to supply exchange rates include: +

+
    +
  • + Data accuracy: Oracles must provide accurate data for DeFi applications to + function correctly. Inaccurate data can cause significant issues, such as + incorrect pricing or faulty execution of smart contracts. +
  • +
  • + Data availability: If an oracle experiences downtime or fails to update its + data feed, the DeFi applications relying on it might not function correctly + or become temporarily unusable, leading to potential losses for users. +
  • +
  • + Latency: The time it takes for an oracle to fetch, process, and transmit + data to a smart contract can impact the performance and efficiency of DeFi + applications. High latency could lead to outdated data or missed + opportunities. +
  • +
  • + Oracle manipulation: Bad actors might attempt to manipulate an oracle's + data feed to influence the outcome of a smart contract or profit from price + discrepancies. This can lead to unintended consequences, such as + liquidations, loss of funds, or arbitrage opportunities for attackers. +
  • +
  • + Centralization risk: If an oracle relies on a centralized data source or a + small number of data providers, it becomes a single point of failure. This + centralization goes against the core principles of decentralization in the + DeFi ecosystem and exposes the system to potential manipulation or downtime. +
  • +
  • + Exploitation of vulnerabilities: Oracles themselves can have security + vulnerabilities, which, if exploited, can compromise the entire DeFi system + relying on them. +
  • +
+
+
+
Rate provider cross-chain bridge risk
+

+ Pools may use rate providers that are bridged between blockchain networks. +

+

+ For example, some pools on Polygon zkEVM use a rate provider that is bridged + from Ethereum Mainnet via the Layer Zero (an omnichain messaging service). In + these pools, LPs are exposed to risk of significant losses if an incorrect + rate is received via the omnichain messaging service. +

+
+
+
+ +
+

+ Boosted Pools +

+

+ Typically, only 10% or less of the liquidity deposited into an AMM pool is being + utilized by traders because the trade sizes are much smaller than the available + liquidity. Boosted Pools allow the remaining portion of liquidity to be sent to + lending protocols where the liquidity can earn additional yield for accepting + inherent risks. +

+
    +
  • + Boosted Pools are designed to allow for greater capital efficiency, deeper + liquidity, and increased yield for Liquidity Providers. +
  • +
  • + For traders, Boosted Pools are a cheaper entry/exit into lending protocols + like Aave. +
  • +
  • + Boosted Pools increase the opportunity for LPs to gain exposure to a wide + variety of yield increases from multiple yield protocols. +
  • +
+
Third party lending platform risk exposure (DeFi composability risk)
+

+ Since boosted pools deposit excess liquidity into lending protocols, like Aave, + to generate yield, LPs must fully understand the risks of the underlying lending + protocol since a portion of their funds will be exposed to the risks of that + protocol. Some of the risks of the underlying lending protocol may include smart + contract bugs, economic attack vulnerabilities and counterparty risk from the + protocol’s borrowers. Lending platforms may also use{' '} + + Oracles + {' '} + which face additional risks (described above). +

+ +

+ Also note, some Boosted pools, like those by Tetu and Idle may use strategies + that utilize multiple yield protocols in order to maximize yield. Since these + strategies may change exposure to the underlying yield protocols at any time, + LPs must accept the risk that the protocol utilizing these strategies carefully + vets all third party protocols to reduce composability risks. +

+ +

+ If the underlying lending protocol were to get hacked, LPs in a boosted pool + that deposits liquidity in that protocol could lose funds. +

+
Depegging risk
+

+ Individual stablecoin tokens within Boosted Pools are subject to{' '} + + depegging risks + + , as described above. +

+
+
+ + +
+

+ Concentrated Liquidity Pools +

+

+ Gyroscope’s  ‘Concentrated + Liquidity Pools’ (CLPs) are a class of AMMs that price the exchange of + assets within a defined range. As such, any CLP only provides liquidity for + trading activity restricted to this specific region. The goal is to use the + pool’s capital efficiently. There’s a few different types of CLPs: +

+
    +
  • + 2-CLPs: Pools with two assets, known as Quadratic-CLPs or 2-CLPs, + named after the quadratic invariant curve—are similar to Uniswap v3’s + concentrated liquidity pools. But unlike Uniswap, a 2-CLP effectively offers a + ‘single tick’, where liquidity is distributed evenly across a + single active trading range. Learn more about{' '} + + 2-CLP’s and their risks + + . +
  • +
  • + 3-CLPs: Pools with three assets, known as Cubic-CLPs or 3-CLPs, + support three assets and are functionally best understood as an extension of + 2-CLPs. As a high-level summary, they amplify the benefits of 2-CLPs. Learn + more about{' '} + + 3-CLP’s and their risks + + . +
  • +
  • + E-CLPs: Also known as ‘Elliptic-CLPs’ support asymmetric + concentrated liqudity for two assets. They provide a new type of concentrated + liquidity that allows highly flexible and asymmetric liquidity profiles in a + single pool position. Learn more about{' '} + + E-CLP’s and their risks + + . +
  • +
  • + Rehype E-CLPs: Arguably the most capital efficient pools, these + E-CLPs combine asymmetric concentrated liquidity with auto-rehypothecation to + lending markets. Learn more about{' '} + + Rehype E-CLP’s and their risks + + . +
  • +
+

+ Other risks: +

    +
  • + The Balancer UI allows people to manage their liquidity in certain Gyroscope + pools. This is not an endorsement of their products or of the the safety of + their smart contracts. The Gyroscope GYD system and E-CLPs have been audited + several times. You can review the{' '} + + audit reports here + + . +
  • +
  • + Some concentrated liquidity pools also contain Gyroscope’s Gyro + Dollars (GYD). Here are some of the{' '} + + risks of using GYD + + . +
  • +
+

+
+
+ + + +
+

+ Network risks (L2s and Sidechains) +

+

+ Sidechains and Layer 2 networks can offer advantages over Ethereum Mainnet, like + faster transaction times and lower fees. However, they come with their own set + of risks and trade-offs. +

+

+ For example, sidechains and Layer 2 networks often have a different security + models. They may rely on a smaller set of validators or different consensus + mechanisms, which could potentially make them more susceptible to attacks or + centralization risks. +

+

+ In addition, there are bridging risks when user’s move funds between + networks. Asset bridges rely on smart contracts to facilitate transfers between + Ethereum Mainnet and Layer 2/sidechains. These contracts may have + vulnerabilities, which could expose users' funds to risks during the + bridging process. +

+

+ This list of networks below is not updated regularly and may not reflect all + networks supported by this UI. +

+
+
+ +
+

+ Arbitrum One risks +

+

+ Arbitrum is a Layer 2 scaling solution for + Ethereum that uses Optimistic Rollups to improve transaction throughput and + reduce fees. +

+

+ View the risks of using Arbitrum on{' '} + L2Beat. +

+
+
+
+
+

+ Optimism risks +

+

+ Optimism is a Layer 2 scaling solution for + Ethereum that uses Optimistic Rollups to improve transaction throughput and reduce + fees. Although, the Balancer App UI doesn’t support Optimism, the Balancer + Protocol smart contracts are deployed on Optimism and currently used by{' '} + Beethoven X. +

+

+ View the risks of using Optimism on{' '} + L2Beat. +

+
+
+ +
+

+ Base Chain risks +

+

+ Base is an Optimistic Rollup that has been + developed on the Ethereum network by Coinbase. It utilizes OP Stack technology from + Optimism. +

+

+ View the risks of using Base on{' '} + L2Beat. +

+
+
+ +
+

+ Polygon PoS risks +

+

+ Polygon PoS is Proof-of-Stake (PoS) + sidechain scaling solution that runs in parallel to Ethereum Mainnet. Its validators + are solely responsible for validating Polygon transactions. It does not derive + security from Ethereum Mainnet. +

+

+ Polygon is subject to the same risks of other PoS chains. In particular, it has a + smaller pool of capital and validator set to gain consensus compared to Ethereum + Mainnet. +

+
+
+ +
+

+ Polygon zkEVM risks +

+

+ Polygon zkEVM is a + EVM-compatible ZK Rollup built by Polygon Labs. Polygon zkEVM harnesses the power of + ZK proofs to reduce transaction costs and massively increase throughput, all while + inheriting the security of Ethereum L1. +

+

+ View the risks of using Polygon zkEVM on{' '} + L2Beat. +

+
+
+ +
+ {' '} +

+ Gnosis chain risks +

+

+ Gnosis Chain, formerly known as xDai Chain, is + a sidechain for Ethereum focused on providing fast, stable, and cost-effective + transactions. It uses a PoS consensus mechanism and is secured by a set of + independent validators. It does not derive security from Ethereum Mainnet. +

+

+ The Gnosis chain is subject to the same risks of other PoS chains. In particular, it + has a smaller pool of capital and validator set to gain consensus compared to + Ethereum Mainnet. +

+
+
+ +
+

+ Avalanche risks +

+

+ Avalanche is a Layer 1 blockchain that is + completely independent from the Ethereum blockchain. It's actually a + heterogeneous network of blockchains which allows separate chains to be created for + different applications. +

+

+ A Subnet is a sovereign network which defines its own rules regarding its membership + and token economics. The security of assets within a specific subnet is directly + tied to the security and integrity of its validators.{' '} +

+

+ Since Avalanche is independent from Ethereum, user's may face additional risks + around briding assets.{' '} +

+
+ + +
+ +
+

+ Navigating these challenges calls for active engagement and open communication + within the community. Sharing insights, feedback, or concerns can contribute to + building a safer and more inclusive environment for all. Please feel free to reach + out with any questions, suggestions or propose changes for this page directly via + the{' '} + + Balancer Github + + . +

+
+
+
+
+
+ ) +} diff --git a/apps/beets-frontend-v3/app/(marketing)/terms-of-use/page.tsx b/apps/beets-frontend-v3/app/(marketing)/terms-of-use/page.tsx new file mode 100644 index 000000000..ae2c09b1a --- /dev/null +++ b/apps/beets-frontend-v3/app/(marketing)/terms-of-use/page.tsx @@ -0,0 +1,596 @@ +'use client' + +import Link from 'next/link' +import { Container } from '@chakra-ui/react' +import { Prose } from '@nikolovlazar/chakra-ui-prose' +import FadeInOnView from '@repo/lib/shared/components/containers/FadeInOnView' + +export default function Terms() { + return ( + + + +
+

Balancer Terms of Use

+

+ Last updated: August 2024 +

+

+ + Do not access this site where such access is prohibited by applicable law. Please + carefully read these terms of use before using the site. These terms apply to any + person or entity accessing the site and by using the site you agree to be bound by + them. The terms of use contain a mandatory individual arbitration and class + action/jury trial waiver provision that requires the use of arbitration on an + individual basis to resolve disputes, rather than jury trials or class actions. If + you do not want to be bound by these terms of use, you should not access the site. + By using the site in any capacity, you agree that you have read, understood, and + agree to be subject to these terms of use. + +

+
+
+ +
+

1. Overview

+

+ This Balancer Terms of Use document (“Terms” or “agreement”) (“Balancer ”, “we” and + “us” refers to the Balancer Foundation and its subsidiary Balancer OpCo Limited) + covers the website, Balancer Protocol user-interface and free application + (collectively “the Site”) we own and administer, at times in conjunction with others, + which provides the ability to access the decentralized Balancer Protocol. + Additionally, you can access the Balancer Protocol through third-party web or mobile + interfaces. These Terms apply to you (“You” or “you”) as a user of our Site including + all the products, services, tools and information, without limitation, made available + on the Site. +

+

+ To avoid any confusion, you agree a) you retain full control, at all times, over your + cryptocurrency assets, b) there are no intermediaries involved when you interact with + the Balancer Protocol and c) the online interface (UI) is a mere graphical interface + for you to interact with the Balancer protocol, which can be accessed through other + means, including other interfaces. +

+

+ You must be able to form a legally binding contract online either as an individual or + on behalf of a legal entity. You represent that, if you are agreeing to these Terms on + behalf of a legal entity, you have the legal authority to bind that entity to these + Terms and you are not indirectly or directly included on any sanctions list and at + least 18 years old or the age of majority where you reside, (whichever is older) can + form a legally binding contract online, and have the full, right, power and authority + to enter into and to comply with the obligations under these Terms. +

+

+ You are advised to periodically review these Terms so you understand any changes to + the Terms. Balancer in its sole discretion, reserves the right to make changes to our + Terms. Changes are binding on users of the Site and will take effect immediately upon + posting. As a user, you agree to be bound by any changes, variations, or modifications + to our Terms and your continued use of the Site shall constitute acceptance of any + such changes, revisions, variations, or modifications. When we make changes, we will + make the updated Terms available on the interface and update the “Last Updated” date + at the beginning of the Terms accordingly. +

+

+ You accept such changes, by continuing to use the Site and by doing so you agree that + we have provided you with sufficient notice of such change. Our{' '} + Privacy policy and{' '} + Cookies policy also apply to your access and use of + the Site. You are entering into a binding Agreement. Any failure by us to exercise any + rights or provisions of the Agreement shall not constitute a waiver of such right or + provision. +

+
+
+ +
+

2. Site

+

+ As part of the Site, Balancer provides access to a decentralized finance application + (“Application” or “Balancer Protocol app”) on the Ethereum blockchain, that allows + swappers or liquidity providers of Ethereum assets (“Cryptocurrency Assets”) to + transact using smart contracts (“Smart Contracts”). Use of the Balancer Protocol may + require that you pay a fee, such as gas charges on the Ethereum network to perform a + transaction. You acknowledge and agree that Balancer has no control over any + activities, transactions, the method of payment of any transactions, or any actual + processing of payments of transactions. You must ensure that you have a sufficient + balance to complete any transaction on the Balancer Protocol before initiating such + transaction. You should not take or refrain from taking any action based on any + information contained on the Site or any other available information at any time. + Before you make any legal, technical, or financial decisions involving the Services, + you should seek independent professional advice from a licensed and qualified + individual in the area for which such advice would be appropriate. +

+

+ + You acknowledge and agree that Balancer has no control over any transactions + conducted through the Balancer Protocol, the method of payment of any transactions + or any actual payments of transactions including use of any third-party services + such as Metamask, or other wallet services. + + Likewise, you must ensure that you have a sufficient balance of the applicable + cryptocurrency tokens stored at your Balancer Protocol-compatible wallet address + (“Cryptocurrency Wallet”) to complete any transaction on the Balancer Protocol or the + Ethereum network before initiating such transaction. +

+

+ You acknowledge and accept the material potential risks associated with using the + smart contracts that can be accessed via the Balancer user interface including, + without limitation, the smart contracts for Balancer Pools. Before using these + features or Pools, please confirm you understand the functionality and risks. For more + information about the risks, please carefully read risks. +

+
+
+ +
+

3. Access / Disclaimer of Warranties

+

+ ACCESS TO THIS SITE AND THE PRODUCTS HEREIN ARE PROVIDED ON AN `'`AS IS`'` + AND `'`AS AVAILABLE`'` BASIS WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. NO WARRANTY IS PROVIDED THAT + THE SITE OR ANY PRODUCT WILL BE FREE FROM DEFECTS OR VIRUSES OR THAT OPERATION OF THE + PRODUCT WILL BE UNINTERRUPTED. YOUR USE OF THE SITE AND ANY PRODUCT AND ANY MATERIAL + OR SERVICES OBTAINED OR ACCESSED VIA THE SITE IS AT YOUR OWN DISCRETION AND RISK, AND + YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE RESULTING FROM THEIR USE. SOME JURISDICTIONS + DO NOT ALLOW THE EXCLUSION OF CERTAIN WARRANTIES, SO SOME OF THE ABOVE LIMITATIONS MAY + NOT APPLY TO YOU. TRANSACTIONS THAT ARE RECORDED VIA THE SITE MUST BE TREATED AS + PERMANENT AND CANNOT BE UNDONE BY US OR BY ANYONE. +

+

+ We do not guarantee or promise that the Site, or any content on it, will always be + available, functional, usable or uninterrupted. From time to time, access may be + interrupted, suspended or restricted, including because of a fault, error or + unforeseen circumstances or because we are carrying out planned maintenance or + changes. You acknowledge and agree that you will access and use the site at your own + risk. By using the Site, you will be solely responsible for conducting your own due + diligence into the risks of a transaction. +

+

+ We reserve the right to limit the availability of the site to any person, geographic + area or jurisdiction in our sole discretion and/or to terminate your access to and use + of the site, at any time and in our sole discretion. We may suspend or disable your + access to the Site for any reason and in our sole discretion, including for any + intentional or unintentional breaches of these Terms. We may remove or amend the + content of the Site at any time. Some of the content may be out of date at any given + time and we are under no obligation to update or revise it. We do not promise or + guarantee that the Site, or any content on it, will be free from errors or omissions. +

+

+ We will not be liable to you for any issue, loss or damage you may or have suffered as + a result of the Site being unavailable at any time for any reason. You will comply + with all applicable domestic and international laws, statutes, ordinances, rules and + regulations applicable to your use of the site (“Applicable Laws”). Likewise, we are + not liable for any third-party services and are not responsible for the content or + services of these party’s. +

+

+ As a condition to accessing or using the Site, you agree and represent that you will: +

+
    +
  • + Only use the Services and the Site for lawful purposes and in adherence with these + Terms; +
  • +
  • + Ensure that all information that you provide on the Site is current, complete, and + accurate; and +
  • +
  • + Maintain the security, privacy and confidentiality of access to your cryptocurrency + wallet address. +
  • +
+

As a condition to accessing or using the Site or the Services, you will not:

+
    +
  • + Violate any Applicable Law, including, without limitation, any relevant and + applicable anti-money laundering and anti-terrorist financing and sanctions laws and + any relevant and applicable privacy, secrecy and data protection laws. +
  • +
  • + Use the Site for any purpose or conduct that is directly or indirectly unlawful; +
  • +
  • + Export, reexport, or transfer, directly or indirectly, any Balancer technology in + violation of applicable export laws or regulations; +
  • +
  • + Infringe on or misappropriate any contract, intellectual property or other + third-party right, or commit a tort while using the Site; +
  • +
  • + Misrepresent, with omission or otherwise, the truthfulness, sourcing or reliability + of any content on the Site; +
  • +
  • + Use the Site in any manner that could interfere with, disrupt, negatively affect, + redirect or inhibit other users from fully enjoying the Site or the Balancer + Protocol, or that could damage, disable, overburden, or impair the functioning of + the Site or the Balancer Protocol in any manner; +
  • +
  • + Attempt to circumvent or disable any content filtering techniques or security + measures that Balancer employs on the Site, or attempt to access any service or area + of the Site that you are not authorized to access; +
  • +
  • + Use any robot, spider, crawler, scraper, or other automated means or interface not + provided by us, to access the Site to extract data; +
  • +
  • + Introduce or use any malware, virus, Trojan horse, worm, logic bomb, drop-dead + device, backdoor, shutdown mechanism or other harmful material into the Site; +
  • +
  • + Post content or communications on the Site that are, in our sole discretion, + libelous, defamatory, profane, obscene, pornographic, sexually explicit, indecent, + lewd, vulgar, suggestive, harassing, hateful, threatening, offensive, + discriminatory, bigoted, abusive, inflammatory, fraudulent, deceptive or otherwise + objectionable; +
  • +
  • + To the extent applicable, post content on the Site containing unsolicited + promotions, commercial messages or any chain messages or user content designed to + deceive, induce or trick the user of the Site; or +
  • +
  • + Encourage or induce any third party to engage in any of the activities prohibited + under these Terms. +
  • +
+
+
+ +
+

+ 3(a). You acknowledge that the Site and your use of the Site present certain risks, + including without limitation the following risks: +

+
    +
  • + Losses while digital assets are being supplied to the Balancer Protocol and losses + due to the fluctuation of prices of tokens in a swapping pair or liquidity pool. + Prices of digital currencies, tokens and/or other digital assets fluctuate day by + day or even minute by minute. The value of your available balance could surge or + drop suddenly. Please note that there is a possibility that the price of tokens + could decrease to zero. Prices of tokens are prone to significant fluctuations, for + example, due to announced proposed legislative acts, governmental restrictions, news + related to cyber crimes or other factors causing potentially excessive market + enthusiasm, disproportionate loss in confidence, or manipulation by others in the + market. +
  • +
  • + Risks associated with accessing the Balancer Protocol through third party web or + mobile interfaces. You are responsible for doing your own diligence on those + interfaces to understand and accept the risks that use entails. You are also + responsible for doing your own diligence on those interfaces to understand and + accept any fees that those interfaces may charge. +
  • +
  • Risks associated with any Smart Contracts with which you interact.
  • +
  • + Although Balancer does not have access to your assets, you are reminded and + acknowledge that at any time, your access to your Cryptocurrency Assets through + third party wallet services, unrelated to Balancer or the Balancer.Fi website, may + be suspended or terminated or there may be a delay in your access or use of your + Cryptocurrency Assets, which may result in the Cryptocurrency Assets diminishing in + value or you being unable to complete a Smart Contract. +
  • +
  • + + You are reminded of the inherent risks with digital assets and decentralized + finance including the fact that tokens are not legal tender and are not backed by + any government. + + Unlike fiat currencies, which are regulated and backed by local governments and + central banks, tokens are based only on technology and user consensus, which means + that in cases of manipulations or market panic, central governments will not take + any corrective actions or measures to achieve stability, maintain liquidity or + protect their value. There is a possibility that certain transactions cannot be + settled or may be difficult to settle, or can be completed only at significantly + adverse prices depending on the market situation and/or market volume. Transactions + may be irreversible, and, accordingly, potential losses due to fraudulent or + accidental transactions are not recoverable. Some blockchain transactions are deemed + to be completed when recorded on a public ledger, which is not necessarily the date + or time when you or another party initiated the transaction. +
  • +
  • + The regulatory frameworks applicable to blockchain transactions in connection with + tokens are still developing and evolving. It is possible that your transactions or + funds are, or may be in the future, subject to various reporting, tax or other + liabilities and obligations. Legislative and regulatory changes or actions at the + country or international level may materially and adversely affect the use, + transfer, exchange, and value of your tokens. +
  • +
  • + The site and/or application may be wholly or partially suspended or terminated for + any or no reason, which may limit your access to your Cryptocurrency Assets. +
  • +
  • + You are solely responsible for understanding and complying with any and all + Applicable Laws in connection with your acceptance of these Terms and your use of + any part of the Site, including but not limited to those related to taxes as well as + reporting and disclosure obligations. +
  • +
  • + This list of risk factors is non-exhaustive, and other risks, arising either now or + in the future, could additionally be relevant and applicable to you in making an + informed judgment to accept, or continue to accept, these Terms and/or use, or + continue to use the Site. +
  • +
+ +

Violating our rules may result in our intervention.

+

+ You agree and acknowledge that if you use the Site and its Services to engage in + conduct prohibited by applicable law, we reserve the right to completely or partially + restrict or revoke your access to the Services at our sole discretion. We reserve the + right to investigate violations and prosecute any suspected breaches of this + Agreement, including the Terms. Any information may be disclosed to satisfy any new + regulation, law, government request, or legal process. +

+ +

Accordingly, you expressly agree that:

+
    +
  1. + you assume all risk in connection with the specific risks identified above in 3(a); +
  2. +
  3. + you assume all risk in connection with your access to and use of the Site, the + Application and the Smart Contracts; +
  4. +
  5. + that you expressly waive and release Balancer from any and all liability, claims, + causes of action, responsibility or damages arising from or in any way related to + your use of the Site, the Application or the Smart Contracts. +
  6. +
  7. + upgrades and modifications to the protocol are managed in a community-driven way by + holders of the Balancer Protocol governance token. No developer or entity involved + in creating the Balancer Protocol will be liable for any claims or damages + whatsoever associated with your use, inability to use, or your interaction with + other users of, the Balancer Protocol, including any direct, indirect, incidental, + special, exemplary, punitive or consequential damages, or loss of profits, + cryptocurrencies, tokens, or anything else of value. +
  8. +
+
+
+ +
+

4. Third-Party Content

+

+ The Site may contain hyperlinks or references to third party websites or content. Any + such hyperlinks or references are provided for your information and convenience only. + We have no control over third party websites and accept no legal responsibility for + any content, material or information contained in them. The display of any hyperlink + and reference to any third-party website does not mean that we endorse that third + party`'`s website, products or services or opine on the accuracy or reliability + of such information. Your use of a third-party site may be governed by the terms and + conditions of that third-party site. +

+
+
+ +
+

5. Our Privacy Policy and Cookies Policy

+

+ Certain areas of our website may record and collect information about you. You can + find more information about how we will process your personal information in our{' '} + Privacy policy. +

+

+ When you use the Site, we may collect information about your computer and your + interaction with the Site. See our Cookies policy{' '} + for more information. +

+
+
+ +
+

6. Intellectual Property Rights

+

+ Balancer is the owner of all intellectual property rights in the Site and the material + published on them. To the extent practical, these works are protected by copyright + laws and all such rights are reserved. www.Balancer.fi is the uniform resource locator + (`'`URL`'`) of Balancer. You will not make use of this URL (or any other URL + owned by us) on another website or digital platform without our prior written consent. + Any unauthorized use or reproduction may be prosecuted. You will retain ownership of + all copyright in data you upload or submit by, through or to the Site. You grant us a + worldwide, royalty-free, irrevocable license to use, copy, distribute or publish and + send this data in any manner. +

+
+
+ +
+

7. Limitation of Liability

+

+ + Under no circumstances shall we or any of our officers, directors, employees, + contractors, agents, affiliates, or subsidiaries be liable to you for any indirect, + punitive, incidental, special, consequential, or exemplary damages, including (but + not limited to) damages for loss of profits, goodwill, use, data, or other + intangible property, arising out of or relating to any access or use of the Site + including the user-interface, nor will we be responsible for any damage, loss, or + injury resulting from hacking, tampering, or other unauthorized access or use of the + Site including the user-interface or the information contained within it. + +

+

+ + We assume no liability or responsibility for any: (a) errors, mistakes, or + inaccuracies of content; (b) personal injury or property damage, of any nature + whatsoever, resulting from any access or use of the Site including the + user-interface; (c) unauthorized access or use of any secure server or database in + our control, or the use of any information or data stored therein; (d) interruption + or cessation of function related to the Site; (e) bugs, viruses, trojan horses, or + the like that may be transmitted to or through the Site; (f) errors or omissions in, + or loss or damage incurred as a result of the use of, any content made available + through the Site; and (g) the defamatory, offensive, or illegal conduct of any third + party. + +

+

+ + Under no circumstances shall we or any of our officers, directors, employees, + contractors, agents, affiliates, or subsidiaries be liable to you for any claims, + proceedings, liabilities, obligations, damages, losses, or costs in an amount + exceeding $100.00. This limitation of liability applies regardless of whether the + alleged liability is based on contract, tort, negligence, strict liability, or any + other basis, and even if we have been advised of the possibility of such liability. + Some jurisdictions do not allow the exclusion of certain warranties or the + limitation or exclusion of certain liabilities, but your acceptance of these Terms + constitutes an agreement to limit the liability of Balancer and our officers, + directors, employees, contractors, agents, affiliates, or subsidiaries to the + maximum extent possible under any applicable laws. + +

+
+
+ +
+

8. Disclaimers

+

We do not guarantee that the Site will be secure or free from bugs or viruses.

+

+ You are responsible for configuring your information technology, computer programs + and/or platform in order to access the Site. You should use and deploy your own virus + protection and security software. We cannot promise that the use of the Site, or any + content taken from the Site, will not infringe the rights of any third party. +

+

+ The content and materials available on the Site are for informational purposes only + and are not intended to address your particular requirements or needs. In particular, + the content and materials available on the Site do not constitute any form of advice, + referral or recommendation by us, should not be regarded as an offer, solicitation, + invitation or recommendation to buy or sell tokens or any other financial services and + is not intended to be relied upon by you in making any specific decision to buy or + sell a token. + + We recommend that you seek independent advice from financial, legal and tax advisors + before making any such decision particularly in light of the risks associated with + digital assets. + +

+

+ Nothing included in the site constitutes an offer or solicitation to sell, or + distribution of, investments and related services to anyone in any jurisdiction. +

+

+ From time to time, reference may be made to data we have gathered. These references + may be selective or, may be partial. As markets change continuously, previously + published information and data may not be current and should not be relied upon. +

+
+
+ +
+

9. Indemnification

+

+ You agree to indemnify and hold Balancer and our officers, directors, employees, + contractors, agents, affiliates, or subsidiaries harmless from any claim or demand, + including attorneys’ fees and costs, made by any third-party due to or arising out of + 1) your use of the site or 2) this agreement. +

+
+
+ +
+

10. General

+

+ We may perform any of our obligations, and exercise any of the rights granted to us + under these Terms, through an affiliated or unaffiliated third-party. We may assign + any or all our rights and obligations under these Terms to any third-party. +

+

+ If any clause or part of any clause of these Terms is found to be void, unenforceable + or invalid, then it will be severed from these Terms, leaving the remainder in full + force and effect, provided that the severance has not altered the basic nature of + these Terms. +

+

+ No single or partial exercise, or failure or delay in exercising any right, power or + remedy by us shall constitute a waiver by us of, or impair or preclude any further + exercise of, that or any right, power or remedy arising under these terms and + conditions or otherwise. If any of the provisions in these Terms are found to be + illegal, invalid or unenforceable by any court of competent jurisdiction, the + remainder shall continue in full force and effect. +

+

+ All disclaimers, indemnities and exclusions in these Terms shall survive termination + of the Terms and shall continue to apply during any suspension or any period during + which the Site is not available for you to use for any reason whatsoever. +

+

+ These Terms and the documents referred to in them set out the entire agreement between + you and us with respect to your use of the site, Balancer and the services provided + via the site and supersede any and all prior or contemporaneous representations, + communications or agreements (written or oral) made between you or us. +

+

+ + Any dispute, controversy, or claim arising out of or in relation to these Terms, + including the validity, invalidity, breach or termination thereof, shall be settled + by arbitration in accordance with the Cayman Islands Arbitration Law, 2012. There + shall be one arbitrator; the appointing authority may be based on mutual agreement, + be chosen by the parties or in the absence of such agreement, the court may + designate an appointing authority. The seat of the arbitration shall be the Cayman + Islands and the language of the arbitration shall be English. The applicable law + shall be Cayman Islands law or another choice of law determined in Balancer’s sole + discretion. + +

+

+ + With respect to all persons and entities, regardless of whether they have obtained + or used the site for personal, commercial or other purposes, all disputes, + controversies or claims must be brought in the parties’ individual capacity, and not + as a plaintiff or class member in any purported class action, collective action or + other representative proceeding. This waiver applies to class arbitration, and, + unless we agree otherwise, the arbitrator may not consolidate more than one person’s + claims. You agree that, by entering into this agreement, you and Balancer are each + waiving the right to a trial by jury or to participate in a class action, collective + action, or other representative proceeding of any kind. + +

+

+ + There is a Cayman Island International Arbitration Centre expected in the near term, + but in the meantime there is the modern Arbitration Act, 2012. + +

+
+
+ +
+

11. Force Majeure

+

+ There is a risk that transactions effected through the Site may be affected by system + failures resulting from adverse events, natural disasters, pandemics and other + emergencies, as well as unforeseen significant changes in the external environment. + With regards to opportunity loss (e.g., loss of opportunity to place a payment + instruction, resulting in loss of profits which could have been obtained) due to + occurrences such as emergency situations and force majeure events, Balancer is under + no obligation to take any corrective action or measure and shall no under + circumstances be liable for any lost profits or other swapping losses. +

+
+
+ +
+

12. Contact Us

+

+ Balancer is a foundation company organized in the Cayman Islands with an operating + company organized in the British Virgin Islands (BVI). Please contact us if you have + any questions about these Terms or other topics, by sending an email to{' '} + + termsofuse@balancer.finance + + . +

+
+
+
+
+ ) +} diff --git a/apps/beets-frontend-v3/app/api/rpc/[chain]/route.ts b/apps/beets-frontend-v3/app/api/rpc/[chain]/route.ts new file mode 100644 index 000000000..182c2bc00 --- /dev/null +++ b/apps/beets-frontend-v3/app/api/rpc/[chain]/route.ts @@ -0,0 +1,57 @@ +import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' + +type Params = { + params: { + chain: string + } +} + +const ALCHEMY_KEY = process.env.NEXT_PRIVATE_ALCHEMY_KEY || '' + +const chainToRpcMap: Record = { + [GqlChain.Mainnet]: `https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Arbitrum]: `https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Optimism]: `https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Base]: `https://base-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Polygon]: `https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Avalanche]: `https://avax-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Fantom]: `https://fantom-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Sepolia]: `https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Fraxtal]: `https://frax-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Gnosis]: `https://gnosis-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, + [GqlChain.Mode]: undefined, + [GqlChain.Zkevm]: `https://polygonzkevm-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, +} + +function getRpcUrl(chain: string) { + try { + const rpc = chainToRpcMap[chain as GqlChain] + if (!rpc) throw new Error(`Invalid chain: ${chain}`) + return rpc + } catch (error) { + throw new Error(`Invalid chain: ${chain}`) + } +} + +export async function POST(request: Request, { params: { chain } }: Params) { + if (!ALCHEMY_KEY) { + return new Response(JSON.stringify({ error: 'NEXT_PRIVATE_ALCHEMY_KEY is missing' }), { + status: 500, + }) + } + + const rpcUrl = getRpcUrl(chain) + const rpcBody = await request.json() + + const rpcResponse = await fetch(rpcUrl, { + method: 'POST', + body: JSON.stringify(rpcBody), + next: { + revalidate: 0, + }, + }) + + const rpcResponseJson = await rpcResponse.json() + + return Response.json(rpcResponseJson) +} diff --git a/apps/beets-frontend-v3/app/api/sentry-example-api/route.ts b/apps/beets-frontend-v3/app/api/sentry-example-api/route.ts new file mode 100644 index 000000000..d35e11021 --- /dev/null +++ b/apps/beets-frontend-v3/app/api/sentry-example-api/route.ts @@ -0,0 +1,9 @@ +import { NextResponse } from 'next/server' + +export const dynamic = 'force-dynamic' + +// A faulty API route to test Sentry's error monitoring +export function GET() { + throw new Error('Sentry Example API Route Error') + return NextResponse.json({ data: 'Testing Sentry Error...' }) +} diff --git a/apps/beets-frontend-v3/app/api/wallet-check/[address]/route.ts b/apps/beets-frontend-v3/app/api/wallet-check/[address]/route.ts new file mode 100644 index 000000000..bd75e950d --- /dev/null +++ b/apps/beets-frontend-v3/app/api/wallet-check/[address]/route.ts @@ -0,0 +1,58 @@ +import { captureError, ensureError } from '@repo/lib/shared/utils/errors' +import { hours } from '@repo/lib/shared/utils/time' +import { NextResponse } from 'next/server' + +type Params = { + params: { + address: string + } +} + +type ReputationResponse = { + data: Array<{ flags: string[]; address: string; recommendation: string }> +} + +export async function GET(request: Request, { params: { address } }: Params) { + try { + if (!process.env.PRIVATE_HYPERNATIVE_API_ID || !process.env.PRIVATE_HYPERNATIVE_API_SECRET) { + return NextResponse.json({ isAuthorized: true }) + } + + const res = await fetch('https://api.hypernative.xyz/assets/reputation/addresses', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-client-id': process.env.PRIVATE_HYPERNATIVE_API_ID, + 'x-client-secret': process.env.PRIVATE_HYPERNATIVE_API_SECRET, + }, + body: JSON.stringify({ + addresses: [address], + flagIds: ['F-1101', 'F-1111', 'F-1301', 'F-1302'], + expandDetails: true, + }), + next: { + revalidate: hours(12).toSecs(), + }, + }) + + if (!res.ok) { + throw new Error('Failed to fetch reputation. Response status: ' + res.status) + } + + const response: ReputationResponse = await res.json() + const recommendation = response.data[0]?.recommendation + if (!recommendation) { + throw new Error('Invalid reputation response: ' + JSON.stringify(response.data)) + } + + const isAuthorized = recommendation !== 'Deny' + + return NextResponse.json({ isAuthorized }) + } catch (err) { + const error = ensureError(err) + + captureError(error, { extra: { address } }) + + return NextResponse.json({ isAuthorized: true }) + } +} diff --git a/apps/beets-frontend-v3/app/error.tsx b/apps/beets-frontend-v3/app/error.tsx new file mode 100644 index 000000000..65eefa50e --- /dev/null +++ b/apps/beets-frontend-v3/app/error.tsx @@ -0,0 +1,5 @@ +'use client' + +import { PageErrorBoundary } from '@repo/lib/shared/components/errors/ErrorBoundary' + +export default PageErrorBoundary diff --git a/apps/beets-frontend-v3/app/global-error.tsx b/apps/beets-frontend-v3/app/global-error.tsx new file mode 100644 index 000000000..132f9e56c --- /dev/null +++ b/apps/beets-frontend-v3/app/global-error.tsx @@ -0,0 +1,49 @@ +'use client' + +import * as Sentry from '@sentry/nextjs' +import { default as NextError } from 'next/error' +import { useEffect } from 'react' +import { isDev, isStaging } from '@repo/lib/config/app.config' + +/** + * Global Next.js ErrorBoundary (!) Next components are not available + * + * Catches: + * - ssr errors (e.g. fetch) (production only) + * - root layout errors (production only) + * - navigation error (e.g. throw from rendering component during next navigation) + * + * @see https://nextjs.org/docs/app/building-your-application/routing/error-handling#handling-global-errors + */ +export default function GlobalError({ + error, + reset, +}: { + error: Error & { digest?: string } + reset: () => void +}) { + const showResetButton = isDev || isStaging + const href = typeof window === 'undefined' ? undefined : window.location.href + + useEffect(() => { + Sentry.captureException(error) + }, [error]) + + const title = error.digest ? `Something went wrong (${error.digest})` : 'Something went wrong' + + return ( + + + +
+ {href && ( + + + + )} + {showResetButton && } +
+ + + ) +} diff --git a/apps/beets-frontend-v3/app/layout.tsx b/apps/beets-frontend-v3/app/layout.tsx new file mode 100644 index 000000000..7ac450804 --- /dev/null +++ b/apps/beets-frontend-v3/app/layout.tsx @@ -0,0 +1,54 @@ +/* eslint-disable max-len */ +import { Metadata } from 'next' +import { satoshiFont } from '@repo/lib/assets/fonts/satoshi/satoshi' +import NextTopLoader from 'nextjs-toploader' +import { SpeedInsights } from '@vercel/speed-insights/next' +import '@repo/lib/assets/css/global.css' +import { Fathom } from '@repo/lib/shared/services/fathom/Fathom' +import { GlobalAlerts } from '@repo/lib/shared/components/navs/GlobalAlerts' +import { PropsWithChildren } from 'react' +import { Providers } from '@repo/lib/shared/components/site/providers' +import { NavBarContainer } from '@/lib/components/navs/NavBarContainer' +import { FooterContainer } from '@/lib/components/footer/FooterContainer' + +export const metadata: Metadata = { + title: 'Beets DeFi Liquidity Pools', + description: `Explore DeFi liquidity pools and swap tokens. Provide liquidity to accumulate yield from swap fees while retaining your token exposure as prices move.`, + icons: [ + { rel: 'icon', type: 'image/x-icon', url: '/favicon.ico' }, + { + rel: 'icon', + type: 'image/png', + url: '/favicon-light.png', + media: '(prefers-color-scheme: light)', + }, + { + rel: 'icon', + type: 'image/png', + url: '/favicon-dark.png', + media: '(prefers-color-scheme: dark)', + }, + ], +} + +export default function RootLayout({ children }: PropsWithChildren) { + return ( + + + + + + + + {children} + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/manifest.json b/apps/beets-frontend-v3/app/manifest.json new file mode 100644 index 000000000..e2cc06054 --- /dev/null +++ b/apps/beets-frontend-v3/app/manifest.json @@ -0,0 +1,21 @@ +{ + "short_name": "Balancer", + "name": "Balancer", + "description": "Balancer is a battle-tested toolkit for true AMM experimentation and innovation.", + "icons": [ + { + "src": "/images/icons/balancer.svg", + "sizes": "any", + "type": "image/svg+xml" + }, + { + "src": "/favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/apps/beets-frontend-v3/app/not-found.tsx b/apps/beets-frontend-v3/app/not-found.tsx new file mode 100644 index 000000000..99c8be984 --- /dev/null +++ b/apps/beets-frontend-v3/app/not-found.tsx @@ -0,0 +1,37 @@ +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' +import { Button, Heading, VStack, Text } from '@chakra-ui/react' +import { headers } from 'next/headers' +import Link from 'next/link' + +export default async function NotFound() { + const headersList = headers() + + const referer = await headersList.get('referer') + + const poolIdSegment = 6 + const maybePoolId = referer?.split('/')[poolIdSegment] + const isPoolPageNotFound = maybePoolId?.startsWith('0x') + + const title = isPoolPageNotFound ? 'Pool Not Found' : 'Page Not Found' + const description = isPoolPageNotFound + ? `The pool you are looking for does not exist: ${maybePoolId}` + : 'The page you are looking for does not exist' + + const redirectUrl = isPoolPageNotFound ? `/pools` : '/' + const redirectText = isPoolPageNotFound ? 'View All Pools' : 'Return Home' + + return ( + + + {title} + + {description} + + + + + + ) +} diff --git a/apps/beets-frontend-v3/app/opengraph-image.jpg b/apps/beets-frontend-v3/app/opengraph-image.jpg new file mode 100644 index 000000000..53cda0462 Binary files /dev/null and b/apps/beets-frontend-v3/app/opengraph-image.jpg differ diff --git a/apps/beets-frontend-v3/app/robots.ts b/apps/beets-frontend-v3/app/robots.ts new file mode 100644 index 000000000..b317bf8b0 --- /dev/null +++ b/apps/beets-frontend-v3/app/robots.ts @@ -0,0 +1,12 @@ +import { MetadataRoute } from 'next' + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: '*', + allow: '/', + disallow: '/private/', + }, + sitemap: 'https://balancer.fi/sitemap.xml', + } +} diff --git a/apps/beets-frontend-v3/app/sitemap.ts b/apps/beets-frontend-v3/app/sitemap.ts new file mode 100644 index 000000000..35a9d6993 --- /dev/null +++ b/apps/beets-frontend-v3/app/sitemap.ts @@ -0,0 +1,60 @@ +import { MetadataRoute } from 'next' + +export default function sitemap(): MetadataRoute.Sitemap { + return [ + { + url: 'https://balancer.fi', + lastModified: new Date(), + changeFrequency: 'weekly', + priority: 1, + }, + { + url: 'https://balancer.fi/pools', + lastModified: new Date(), + changeFrequency: 'daily', + priority: 0.9, + }, + { + url: 'https://balancer.fi/swap', + lastModified: new Date(), + changeFrequency: 'weekly', + priority: 0.9, + }, + { + url: 'https://balancer.fi/portfolio', + lastModified: new Date(), + changeFrequency: 'weekly', + priority: 0.8, + }, + { + url: 'https://balancer.fi/terms-of-use', + lastModified: new Date(), + changeFrequency: 'monthly', + priority: 0.5, + }, + { + url: 'https://balancer.fi/cookies-policy', + lastModified: new Date(), + changeFrequency: 'monthly', + priority: 0.5, + }, + { + url: 'https://balancer.fi/privacy-policy', + lastModified: new Date(), + changeFrequency: 'monthly', + priority: 0.5, + }, + { + url: 'https://balancer.fi/risks', + lastModified: new Date(), + changeFrequency: 'monthly', + priority: 0.5, + }, + { + url: 'https://balancer.fi/3rd-party-services', + lastModified: new Date(), + changeFrequency: 'monthly', + priority: 0.5, + }, + ] +} diff --git a/apps/beets-frontend-v3/instrumentation.ts b/apps/beets-frontend-v3/instrumentation.ts new file mode 100644 index 000000000..5316f8eb2 --- /dev/null +++ b/apps/beets-frontend-v3/instrumentation.ts @@ -0,0 +1,9 @@ +export async function register() { + if (process.env.NEXT_RUNTIME === 'nodejs') { + await import('./sentry.server.config') + } + + if (process.env.NEXT_RUNTIME === 'edge') { + await import('./sentry.edge.config') + } +} diff --git a/apps/beets-frontend-v3/lib/components/footer/FooterContainer.tsx b/apps/beets-frontend-v3/lib/components/footer/FooterContainer.tsx new file mode 100644 index 000000000..635be623f --- /dev/null +++ b/apps/beets-frontend-v3/lib/components/footer/FooterContainer.tsx @@ -0,0 +1,20 @@ +import { BeetsLogoType } from '../imgs/BeetsLogoType' +import { useNavData } from '../navs/useNavData' +import { useFooterData } from './useFooterData' +import { Footer } from '@repo/lib/shared/components/navs/Footer' + +export function FooterContainer() { + const { linkSections, legalLinks } = useFooterData() + const { getSocialLinks } = useNavData() + + return ( +