Skip to content
This repository was archived by the owner on Oct 15, 2024. It is now read-only.

Commit 78e5b3f

Browse files
committed
Merge branch 'main' of github.com:balancer/frontend-v3 into feat/cross-chain-sync
2 parents 76a0495 + 1a6ffc2 commit 78e5b3f

24 files changed

+227
-87
lines changed

.env.template

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ PRIVATE_HYPERNATIVE_API_SECRET=xxx
1010
PRIVATE_CURRENCYAPI_KEY=xxx
1111

1212
# For integration tests and rpc proxy routes (optional)
13-
NEXT_PRIVATE_ALCHEMY_KEY=xxx
1413
NEXT_PRIVATE_DRPC_KEY=xxx
1514

1615
# Allow skip transaction (optional)

.github/workflows/checks.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ on:
66
env:
77
NEXT_PUBLIC_BALANCER_API_URL: https://api-v3.balancer.fi/graphql
88
NEXT_PUBLIC_WALLET_CONNECT_ID: ${{ secrets.NEXT_PUBLIC_WALLET_CONNECT_ID }}
9-
NEXT_PRIVATE_ALCHEMY_KEY: ${{ secrets.PRIVATE_ALCHEMY_KEY }}
109
NEXT_PRIVATE_DRPC_KEY: ${{ secrets.PRIVATE_DRPC_KEY }}
1110

1211
jobs:
@@ -53,5 +52,7 @@ jobs:
5352
uses: ./.github/actions/setup
5453
- name: Set up foundry (includes anvil)
5554
uses: foundry-rs/foundry-toolchain@v1
55+
with:
56+
cache: false
5657
- name: Run integration tests
5758
run: pnpm test:integration

app/(app)/pools/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Suspense } from 'react'
99
// import { getProjectConfig } from '@/lib/config/getProjectConfig'
1010
// import { GetFeaturedPoolsDocument } from '@/lib/shared/services/api/generated/graphql'
1111
// import { FeaturedPools } from '@/lib/modules/featured-pools/FeaturedPools'
12-
import { CowGalxeQuestPromoBanner } from '@/lib/shared/components/promos/CowGalxeQuestPromoBanner'
12+
import { CowPromoBanner } from '@/lib/shared/components/promos/CowPromoBanner'
1313

1414
export default async function PoolsPage() {
1515
// Featured pools set up
@@ -33,7 +33,7 @@ export default async function PoolsPage() {
3333
<DefaultPageContainer pt={['xl', '40px']} pb={['xl', '2xl']}>
3434
<FadeInOnView animateOnce={false}>
3535
<Box>
36-
<CowGalxeQuestPromoBanner />
36+
<CowPromoBanner />
3737
</Box>
3838
</FadeInOnView>
3939
{/* <FadeInOnView animateOnce={false}>

app/api/rpc/[chain]/route.ts

+14-18
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@ type Params = {
66
}
77
}
88

9-
const ALCHEMY_KEY = process.env.NEXT_PRIVATE_ALCHEMY_KEY || ''
109
const DRPC_KEY = process.env.NEXT_PRIVATE_DRPC_KEY || ''
10+
const dRpcUrl = (chainName: string) =>
11+
`https://lb.drpc.org/ogrpc?network=${chainName}&dkey=${DRPC_KEY}`
1112

1213
const chainToRpcMap: Record<GqlChain, string | undefined> = {
13-
[GqlChain.Mainnet]: `https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
14-
[GqlChain.Arbitrum]: `https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
15-
[GqlChain.Optimism]: `https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
16-
[GqlChain.Base]: `https://base-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
17-
[GqlChain.Polygon]: `https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
18-
[GqlChain.Avalanche]: `https://avax-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
19-
[GqlChain.Fantom]: `https://fantom-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
20-
[GqlChain.Sepolia]: `https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_KEY}`,
21-
[GqlChain.Fraxtal]: `https://frax-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
22-
[GqlChain.Gnosis]: `https://lb.drpc.org/ogrpc?network=gnosis&dkey=${DRPC_KEY}`,
23-
[GqlChain.Mode]: undefined,
24-
[GqlChain.Zkevm]: `https://polygonzkevm-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`,
14+
[GqlChain.Mainnet]: dRpcUrl('ethereum'),
15+
[GqlChain.Arbitrum]: dRpcUrl('arbitrum'),
16+
[GqlChain.Optimism]: dRpcUrl('optimism'),
17+
[GqlChain.Base]: dRpcUrl('base'),
18+
[GqlChain.Polygon]: dRpcUrl('polygon'),
19+
[GqlChain.Avalanche]: dRpcUrl('avalanche'),
20+
[GqlChain.Fantom]: dRpcUrl('fantom'),
21+
[GqlChain.Sepolia]: dRpcUrl('sepolia'),
22+
[GqlChain.Fraxtal]: dRpcUrl('fraxtal'),
23+
[GqlChain.Gnosis]: dRpcUrl('gnosis'),
24+
[GqlChain.Mode]: dRpcUrl('mode'),
25+
[GqlChain.Zkevm]: dRpcUrl('polygon-zkevm'),
2526
}
2627

2728
function getRpcUrl(chain: string) {
@@ -35,11 +36,6 @@ function getRpcUrl(chain: string) {
3536
}
3637

3738
export async function POST(request: Request, { params: { chain } }: Params) {
38-
if (!ALCHEMY_KEY) {
39-
return new Response(JSON.stringify({ error: 'NEXT_PRIVATE_ALCHEMY_KEY is missing' }), {
40-
status: 500,
41-
})
42-
}
4339
if (!DRPC_KEY) {
4440
return new Response(JSON.stringify({ error: 'NEXT_PRIVATE_DRPC_KEY is missing' }), {
4541
status: 500,

lib/modules/pool/actions/PoolActionsPriceImpactDetails.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { NumberText } from '@/lib/shared/components/typography/NumberText'
22
import { fNum, bn } from '@/lib/shared/utils/numbers'
33
import { HStack, VStack, Text, Tooltip, Icon, Box, Skeleton } from '@chakra-ui/react'
44
import { usePriceImpact } from '@/lib/modules/price-impact/PriceImpactProvider'
5-
import { useUserSettings } from '@/lib/modules/user/settings/UserSettingsProvider'
65
import { useCurrency } from '@/lib/shared/hooks/useCurrency'
76
import { usePool } from '../PoolProvider'
87
import { ArrowRight } from 'react-feather'
@@ -13,17 +12,18 @@ import { InfoIcon } from '@/lib/shared/components/icons/InfoIcon'
1312
interface PoolActionsPriceImpactDetailsProps {
1413
bptAmount: bigint | undefined
1514
totalUSDValue: string
15+
slippage: string
1616
isAddLiquidity?: boolean
1717
isLoading?: boolean
1818
}
1919

2020
export function PoolActionsPriceImpactDetails({
2121
bptAmount,
2222
totalUSDValue,
23+
slippage,
2324
isAddLiquidity = false,
2425
isLoading = false,
2526
}: PoolActionsPriceImpactDetailsProps) {
26-
const { slippage } = useUserSettings()
2727
const { toCurrency } = useCurrency()
2828
const { pool } = usePool()
2929

lib/modules/pool/actions/add-liquidity/AddLiquidityProvider.tsx

+11-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { HumanTokenAmountWithAddress } from '@/lib/modules/tokens/token.types'
2929
import { isUnhandledAddPriceImpactError } from '@/lib/modules/price-impact/price-impact.utils'
3030
import { useModalWithPoolRedirect } from '../../useModalWithPoolRedirect'
3131
import { getPoolTokens } from '../../pool.helpers'
32+
import { useUserSettings } from '@/lib/modules/user/settings/UserSettingsProvider'
3233

3334
export type UseAddLiquidityResponse = ReturnType<typeof _useAddLiquidity>
3435
export const AddLiquidityContext = createContext<UseAddLiquidityResponse | null>(null)
@@ -39,12 +40,14 @@ export function _useAddLiquidity(urlTxHash?: Hash) {
3940
const [acceptPoolRisks, setAcceptPoolRisks] = useState(false)
4041
const [wethIsEth, setWethIsEth] = useState(false)
4142
const [totalUSDValue, setTotalUSDValue] = useState('0')
43+
const [proportionalSlippage, setProportionalSlippage] = useState<string>('0')
4244

4345
const { pool, refetch: refetchPool, isLoading } = usePool()
4446
const { getToken, getNativeAssetToken, getWrappedNativeAssetToken, isLoadingTokenPrices } =
4547
useTokens()
4648
const { isConnected } = useUserAccount()
4749
const { hasValidationErrors } = useTokenInputsValidation()
50+
const { slippage: userSlippage } = useUserSettings()
4851

4952
const handler = useMemo(() => selectAddLiquidityHandler(pool), [pool.id, isLoading])
5053

@@ -56,7 +59,8 @@ export function _useAddLiquidity(urlTxHash?: Hash) {
5659
const chain = pool.chain
5760
const nativeAsset = getNativeAssetToken(chain)
5861
const wNativeAsset = getWrappedNativeAssetToken(chain)
59-
62+
const isForcedProportionalAdd = requiresProportionalInput(pool.type)
63+
const slippage = isForcedProportionalAdd ? proportionalSlippage : userSlippage
6064
const tokens = getPoolTokens(pool, getToken)
6165

6266
function setInitialHumanAmountsIn() {
@@ -115,6 +119,7 @@ export function _useAddLiquidity(urlTxHash?: Hash) {
115119
handler,
116120
humanAmountsIn,
117121
simulationQuery,
122+
slippage,
118123
})
119124
const transactionSteps = useTransactionSteps(steps, isLoadingSteps)
120125

@@ -126,7 +131,7 @@ export function _useAddLiquidity(urlTxHash?: Hash) {
126131
const hasQuoteContext = !!simulationQuery.data
127132

128133
async function refetchQuote() {
129-
if (requiresProportionalInput(pool.type)) {
134+
if (isForcedProportionalAdd) {
130135
/*
131136
This is the only edge-case where the SDK needs pool onchain data from the frontend
132137
(calculateProportionalAmounts uses pool.dynamicData.totalShares in its parameters)
@@ -186,6 +191,10 @@ export function _useAddLiquidity(urlTxHash?: Hash) {
186191
addLiquidityTxHash,
187192
hasQuoteContext,
188193
addLiquidityTxSuccess,
194+
slippage,
195+
proportionalSlippage,
196+
isForcedProportionalAdd,
197+
setProportionalSlippage,
189198
refetchQuote,
190199
setHumanAmountIn,
191200
setHumanAmountsIn,

lib/modules/pool/actions/add-liquidity/form/AddLiquidityForm.tsx

+25-10
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import { Address } from 'viem'
2121
import { AddLiquidityModal } from '../modal/AddLiquidityModal'
2222
import { useAddLiquidity } from '../AddLiquidityProvider'
2323
import { bn, fNum } from '@/lib/shared/utils/numbers'
24-
import { TransactionSettings } from '@/lib/modules/user/settings/TransactionSettings'
24+
import {
25+
ProportionalTransactionSettings,
26+
TransactionSettings,
27+
} from '@/lib/modules/user/settings/TransactionSettings'
2528
import { TokenInputs } from './TokenInputs'
2629
import { TokenInputsWithAddable } from './TokenInputsWithAddable'
2730
import { usePool } from '../../../PoolProvider'
@@ -52,10 +55,10 @@ import { useTokens } from '@/lib/modules/tokens/TokensProvider'
5255

5356
// small wrapper to prevent out of context error
5457
export function AddLiquidityForm() {
55-
const { validTokens } = useAddLiquidity()
58+
const { validTokens, proportionalSlippage } = useAddLiquidity()
5659

5760
return (
58-
<TokenBalancesProvider extTokens={validTokens}>
61+
<TokenBalancesProvider extTokens={validTokens} bufferPercentage={proportionalSlippage}>
5962
<AddLiquidityMainForm />
6063
</TokenBalancesProvider>
6164
)
@@ -78,6 +81,9 @@ function AddLiquidityMainForm() {
7881
nativeAsset,
7982
wNativeAsset,
8083
previewModalDisclosure,
84+
proportionalSlippage,
85+
slippage,
86+
setProportionalSlippage,
8187
} = useAddLiquidity()
8288

8389
const nextBtn = useRef(null)
@@ -144,26 +150,34 @@ function AddLiquidityMainForm() {
144150
})
145151
}
146152

147-
useEffect(() => {
148-
if (addLiquidityTxHash) {
149-
previewModalDisclosure.onOpen()
150-
}
151-
}, [addLiquidityTxHash])
152-
153153
function onModalClose() {
154154
// restart polling for token prices when modal is closed again
155155
startTokenPricePolling()
156156

157157
previewModalDisclosure.onClose()
158158
}
159159

160+
useEffect(() => {
161+
if (addLiquidityTxHash) {
162+
previewModalDisclosure.onOpen()
163+
}
164+
}, [addLiquidityTxHash])
165+
160166
return (
161167
<Box w="full" maxW="lg" mx="auto" pb="2xl">
162168
<Card>
163169
<CardHeader>
164170
<HStack w="full" justify="space-between">
165171
<span>Add liquidity</span>
166-
<TransactionSettings size="sm" />
172+
{requiresProportionalInput(pool.type) ? (
173+
<ProportionalTransactionSettings
174+
slippage={proportionalSlippage}
175+
setSlippage={setProportionalSlippage}
176+
size="sm"
177+
/>
178+
) : (
179+
<TransactionSettings size="sm" />
180+
)}
167181
</HStack>
168182
</CardHeader>
169183
<VStack spacing="md" align="start" w="full">
@@ -204,6 +218,7 @@ function AddLiquidityMainForm() {
204218
<PoolActionsPriceImpactDetails
205219
totalUSDValue={totalUSDValue}
206220
bptAmount={simulationQuery.data?.bptOut.amount}
221+
slippage={slippage}
207222
isAddLiquidity
208223
isLoading={isFetching}
209224
/>

lib/modules/pool/actions/add-liquidity/form/TokenInputsWithAddable.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export function TokenInputsWithAddable({
159159
<TokenInputs
160160
tokenSelectDisclosureOpen={tokenSelectDisclosureOpen}
161161
customSetAmountIn={setAmountIn}
162-
></TokenInputs>
162+
/>
163163
</VStack>
164164
)
165165
}

lib/modules/pool/actions/add-liquidity/form/useMaximumInputs.tsx

+9-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { useMemo, useState } from 'react'
1010
import { usePool } from '../../../PoolProvider'
1111
import { useAddLiquidity } from '../AddLiquidityProvider'
1212
import { useTotalUsdValue } from '@/lib/modules/tokens/useTotalUsdValue'
13+
import { TokenAmount } from '@/lib/modules/tokens/token.types'
1314

1415
export function useMaximumInputs() {
1516
const { isConnected } = useUserAccount()
@@ -20,12 +21,15 @@ export function useMaximumInputs() {
2021
const { isLoadingTokenPrices } = useTokens()
2122
const [isMaximized, setIsMaximized] = useState(false)
2223

24+
// Depending on if the user is using WETH or ETH, we need to filter out the
25+
// native asset or wrapped native asset.
26+
const nativeAssetFilter = (balance: TokenAmount) =>
27+
wethIsEth
28+
? wNativeAsset && balance.address !== wNativeAsset.address
29+
: nativeAsset && balance.address !== nativeAsset.address
30+
2331
const filteredBalances = useMemo(() => {
24-
return balances.filter(balance =>
25-
wethIsEth
26-
? wNativeAsset && balance.address !== wNativeAsset.address
27-
: nativeAsset && balance.address !== nativeAsset.address
28-
)
32+
return balances.filter(nativeAssetFilter)
2933
}, [wethIsEth, isBalancesLoading])
3034

3135
function handleMaximizeUserAmounts() {

lib/modules/pool/actions/add-liquidity/form/useProportionalInputs.tsx

+10-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
} from '../../LiquidityActionHelpers'
1818
import { useAddLiquidity } from '../AddLiquidityProvider'
1919
import { useTotalUsdValue } from '@/lib/modules/tokens/useTotalUsdValue'
20-
import { HumanTokenAmountWithAddress } from '@/lib/modules/tokens/token.types'
20+
import { HumanTokenAmountWithAddress, TokenAmount } from '@/lib/modules/tokens/token.types'
2121
import { swapWrappedWithNative } from '@/lib/modules/tokens/token.helpers'
2222

2323
type OptimalToken = {
@@ -42,13 +42,16 @@ export function useProportionalInputs() {
4242
const [isMaximized, setIsMaximized] = useState(false)
4343
const { isLoadingTokenPrices } = useTokens()
4444

45+
// Depending on if the user is using WETH or ETH, we need to filter out the
46+
// native asset or wrapped native asset.
47+
const nativeAssetFilter = (balance: TokenAmount) =>
48+
wethIsEth
49+
? wNativeAsset && balance.address !== wNativeAsset.address
50+
: nativeAsset && balance.address !== nativeAsset.address
51+
4552
const filteredBalances = useMemo(() => {
46-
return balances.filter(balance =>
47-
wethIsEth
48-
? wNativeAsset && balance.address !== wNativeAsset.address
49-
: nativeAsset && balance.address !== nativeAsset.address
50-
)
51-
}, [wethIsEth, isBalancesLoading])
53+
return balances.filter(nativeAssetFilter)
54+
}, [wethIsEth, isBalancesLoading, balances])
5255

5356
function clearAmountsIn(changedAmount?: HumanTokenAmountWithAddress) {
5457
setHumanAmountsIn(

lib/modules/pool/actions/add-liquidity/handlers/ProportionalAddLiquidity.handler.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,13 @@ export class ProportionalAddLiquidityHandler implements AddLiquidityHandler {
4848
account,
4949
queryOutput,
5050
humanAmountsIn,
51+
slippagePercent,
5152
}: SdkBuildAddLiquidityInput): Promise<TransactionConfig> {
5253
const addLiquidity = new AddLiquidity()
5354

5455
const { callData, to, value } = addLiquidity.buildCall({
5556
...queryOutput.sdkQueryOutput,
56-
// Setting slippage to zero ensures the build call can't fail if the user
57-
// maxes out their balance. It can result in a tx failure if the pool
58-
// state changes significantly in the background. The assumption is that
59-
// this should be rare. If not, we will have to re-introduce slippage here
60-
// and limit the user input amounts to their balance - slippage.
61-
slippage: Slippage.fromPercentage('0' as HumanAmount),
57+
slippage: Slippage.fromPercentage(slippagePercent as HumanAmount),
6258
sender: account,
6359
recipient: account,
6460
wethIsEth: this.helpers.isNativeAssetIn(humanAmountsIn),

lib/modules/pool/actions/add-liquidity/modal/AddLiquiditySummary.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function AddLiquiditySummary({
3434
tokens,
3535
addLiquidityTxHash,
3636
addLiquidityTxSuccess,
37+
slippage,
3738
} = useAddLiquidity()
3839
const { pool } = usePool()
3940
const { isMobile } = useBreakpoints()
@@ -123,6 +124,7 @@ export function AddLiquiditySummary({
123124
<PoolActionsPriceImpactDetails
124125
totalUSDValue={totalUSDValue}
125126
bptAmount={simulationQuery.data?.bptOut.amount}
127+
slippage={slippage}
126128
isAddLiquidity
127129
/>
128130
</VStack>

lib/modules/pool/actions/add-liquidity/queries/useAddLiquidityBuildCallDataQuery.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { useUserSettings } from '@/lib/modules/user/settings/UserSettingsProvider'
21
import { useUserAccount } from '@/lib/modules/web3/UserAccountProvider'
32
import { defaultDebounceMs, onlyExplicitRefetch } from '@/lib/shared/utils/queries'
43
import { useQuery } from '@tanstack/react-query'
@@ -19,19 +18,20 @@ export type AddLiquidityBuildQueryParams = {
1918
handler: AddLiquidityHandler
2019
humanAmountsIn: HumanTokenAmountWithAddress[]
2120
simulationQuery: AddLiquiditySimulationQueryResult
21+
slippage: string
2222
}
2323

2424
// Uses the SDK to build a transaction config to be used by wagmi's useManagedSendTransaction
2525
export function useAddLiquidityBuildCallDataQuery({
2626
handler,
2727
humanAmountsIn,
2828
simulationQuery,
29+
slippage,
2930
enabled,
3031
}: AddLiquidityBuildQueryParams & {
3132
enabled: boolean
3233
}) {
3334
const { userAddress, isConnected } = useUserAccount()
34-
const { slippage } = useUserSettings()
3535
const { pool, chainId } = usePool()
3636
const { data: blockNumber } = useBlockNumber({ chainId })
3737
const { relayerApprovalSignature } = useRelayerSignature()

0 commit comments

Comments
 (0)