Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧦 Handle user's invalid network #31

Merged
merged 12 commits into from
Apr 24, 2024
6 changes: 4 additions & 2 deletions packages/frontend/src/blockchain/chain.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { arbitrum, arbitrumSepolia, hardhat } from 'wagmi/chains'

const SUPPORTED_CHAIN_IDS = [arbitrum.id, arbitrumSepolia.id, hardhat.id] as const
export type SupportedChainId = typeof SUPPORTED_CHAIN_IDS[number]
const AllSupportedChains = [hardhat, arbitrum, arbitrumSepolia] as const
export type SupportedChainId = typeof AllSupportedChains[number]['id']

export const SupportedChains = process.env.NODE_ENV === 'production' ? ([arbitrum] as const) : AllSupportedChains
22 changes: 15 additions & 7 deletions packages/frontend/src/blockchain/hooks/useAuctionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export enum ContractState {
}

export function useAuctionState(): AuctionState | undefined {
const { address, chainId } = useAccount()
const { address, chainId: userChainId } = useAccount()
const chainId = useChainId()
const { state, isLoading } = useContractState()
if (isLoading) {
return undefined
Expand All @@ -34,15 +35,15 @@ export function useAuctionState(): AuctionState | undefined {
}

if (state === ContractState.BIDDING_OPEN) {
return getStateUsingWallet(address, chainId, 'BiddingFlow')
return getStateForWallet({ address, userChainId, chainId, state: 'BiddingFlow' })
}

if (state === ContractState.BIDDING_CLOSED || state === ContractState.AUCTION_SETTLED) {
return 'AwaitingResults'
}

if (state === ContractState.RAFFLE_SETTLED) {
return getStateUsingWallet(address, chainId, 'ClaimingFlow')
return getStateForWallet({ address, userChainId, chainId, state: 'ClaimingFlow' })
}

if (state === ContractState.CLAIMING_CLOSED) {
Expand All @@ -64,14 +65,21 @@ export const useContractState = () => {
return { state: data as ContractState, isLoading }
}

function getStateUsingWallet(account: Hex | undefined, chainId: number | undefined, state: AuctionState) {
if (!account) {
interface GetStateForWalletParams {
address: Hex | undefined
userChainId: number | undefined
chainId: number
state: AuctionState
}

function getStateForWallet(params: GetStateForWalletParams): AuctionState {
if (!params.address) {
return 'WalletNotConnected'
}

if (!chainId) {
if (params.userChainId !== params.chainId) {
return 'WrongNetwork'
}

return state
return params.state
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import { BidFlow } from './bid/BidFlow'
import { AwaitingResults } from '@/components/userActious/claim/AwaitingResults'
import { ClaimingClosed } from '@/components/userActious/claim/ClaimingClosed'
import { BidAwaiting } from '@/components/userActious/BidAwaiting'
import { WrongNetworkWarning } from './WrongNetworkWarning'

const Placeholder = () => <div />

const UserActions: Record<AuctionState, () => ReactElement> = {
AwaitingBidding: BidAwaiting,
WalletNotConnected: ConnectWalletWarning,
WrongNetwork: Placeholder,
WrongNetwork: WrongNetworkWarning,
BiddingFlow: BidFlow,
AwaitingResults: AwaitingResults,
ClaimingFlow: Placeholder,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useSwitchChain } from 'wagmi'
import { useContractState } from '@/blockchain/hooks/useAuctionState'
import { getWarningText } from '@/components/userActious/getWarningText'
import { FormHeading, FormRow, FormWrapper } from '@/components/form'
import { Button } from '@/components/buttons'
import { arbitrum } from 'wagmi/chains'

export const WrongNetworkWarning = () => {
const { switchChain } = useSwitchChain()
const { state } = useContractState()
const text = getWarningText(state)

const onSwitch = () => switchChain({ chainId: arbitrum.id })

return (
<FormWrapper>
<FormHeading>{text.heading}</FormHeading>
<FormRow>
<div>
You are connected to the wrong network.
<br></br>
To {text.action} connect your wallet to the <b>Arbitrum network.</b>
</div>
</FormRow>
<Button onClick={onSwitch}>Change network</Button>
</FormWrapper>
)
}
3 changes: 2 additions & 1 deletion packages/frontend/src/config/wagmiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { createConfig, webSocket } from 'wagmi'
import { arbitrum, arbitrumSepolia, hardhat } from 'wagmi/chains'
import { coinbaseWallet, walletConnect } from 'wagmi/connectors'
import { environment } from '@/config/environment'
import { SupportedChains } from '@/blockchain/chain'

export const wagmiConfig = createConfig({
chains: [arbitrum, arbitrumSepolia, hardhat],
chains: SupportedChains,
ssr: true,
transports: {
[arbitrum.id]: webSocket(`wss://arbitrum-mainnet.infura.io/ws/v3/${environment.infuraKey}`),
Expand Down
8 changes: 7 additions & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
"globalDependencies": ["**/.env.*local"],
"pipeline": {
"build": {
"env": ["NEXT_PUBLIC_VOUCHER_REDEEM_DEADLINE", "NEXT_PUBLIC_INFURA_KEY", "NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID", "NEXT_PUBLIC_GITCOIN_REQUIRED_SCORE"],
"env": [
"NEXT_PUBLIC_VOUCHER_REDEEM_DEADLINE",
"NEXT_PUBLIC_INFURA_KEY",
"NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID",
"NEXT_PUBLIC_GITCOIN_REQUIRED_SCORE",
"NODE_ENV"
],
"dependsOn": ["^build"],
"outputs": [".next/**", "!.next/cache/**", "build/**", "cache"]
},
Expand Down