Skip to content

Commit

Permalink
fix: wallet connection UI on the submit page (#720)
Browse files Browse the repository at this point in the history
part of #703 

wagmi's `useReconnect` hook doesn't do what we assumed, and as we're
already using `useAutoReconnect` we'll basically never need it. Instead
for triggering a full wallet reconnect, we can simply pop open the
connectkit modal.

---------

Co-authored-by: Jan-Felix <[email protected]>
  • Loading branch information
jfschwarz and jfschwarz authored Jan 30, 2025
1 parent 32f0ba3 commit 103f256
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 58 deletions.
9 changes: 5 additions & 4 deletions deployables/app/app/components/wallet/ConnectWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { type HexAddress, ProviderType } from '@zodiac/schema'
import { useEffect, useRef } from 'react'
import { type ChainId } from 'ser-kit'
import { useAccount, useAccountEffect, useDisconnect } from 'wagmi'
import { Connect, type OnConnectArgs } from './Connect'
import { EmptyAccount } from './EmptyAccount'
import type { OnConnectArgs } from './LaunchConnectKit'
import { Wallet } from './Wallet'

export type ConnectWalletProps = {
Expand All @@ -24,7 +25,7 @@ export const ConnectWallet = ({

useAutoReconnect({ currentConnectedAddress: pilotAddress, onConnect })

const accountNotConnected =
const pilotAccountIsEmpty =
pilotAddress == null || pilotAddress === ZERO_ADDRESS

const disconnectRequestRef = useRef(false)
Expand All @@ -41,8 +42,8 @@ export const ConnectWallet = ({
},
})

if (accountNotConnected) {
return <Connect onConnect={onConnect} />
if (pilotAccountIsEmpty) {
return <EmptyAccount onConnect={onConnect} />
}

return (
Expand Down
18 changes: 18 additions & 0 deletions deployables/app/app/components/wallet/EmptyAccount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Labeled, PrimaryButton } from '@zodiac/ui'
import { LaunchConnectKit, type OnConnectArgs } from './LaunchConnectKit'

type Props = {
onConnect?: (args: OnConnectArgs) => void
}

export const EmptyAccount = ({ onConnect }: Props) => {
return (
<LaunchConnectKit onConnect={onConnect}>
{({ show }) => (
<Labeled label="Pilot Account">
<PrimaryButton onClick={show}>Connect wallet</PrimaryButton>
</Labeled>
)}
</LaunchConnectKit>
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { ChainId } from '@zodiac/chains'
import { ProviderType, type HexAddress } from '@zodiac/schema'
import { Labeled, PrimaryButton } from '@zodiac/ui'
import { ConnectKitButton, ConnectKitProvider } from 'connectkit'
import {
ConnectKitButton as ConnectKitButtonBase,
ConnectKitProvider,
} from 'connectkit'
import { useAccountEffect } from 'wagmi'

export type OnConnectArgs = {
Expand All @@ -9,10 +12,16 @@ export type OnConnectArgs = {
}

type ConnectProps = {
children: (props: { show?: () => void }) => React.ReactNode
onConnect?: (args: OnConnectArgs) => void
initialChainId?: ChainId
}

export const Connect = ({ onConnect }: ConnectProps) => {
export const LaunchConnectKit = ({
initialChainId,
onConnect,
children,
}: ConnectProps) => {
useAccountEffect({
onConnect({ address, connector, isReconnected }) {
if (isReconnected) {
Expand All @@ -34,14 +43,16 @@ export const Connect = ({ onConnect }: ConnectProps) => {
})

return (
<ConnectKitProvider>
<ConnectKitButton.Custom>
{({ show }) => (
<Labeled label="Pilot Account">
<PrimaryButton onClick={show}>Connect wallet</PrimaryButton>
</Labeled>
)}
</ConnectKitButton.Custom>
<ConnectKitProvider
options={{
initialChainId: initialChainId ?? 0,
hideNoWalletCTA: true,
hideQuestionMarkCTA: true,
}}
>
<ConnectKitButtonBase.Custom>
{({ show }) => children({ show })}
</ConnectKitButtonBase.Custom>
</ConnectKitProvider>
)
}
8 changes: 2 additions & 6 deletions deployables/app/app/components/wallet/Wallet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ChainId } from 'ser-kit'
import { useAccount, useReconnect, useSwitchChain } from 'wagmi'
import { useAccount, useSwitchChain } from 'wagmi'
import { Account } from './Account'
import { Connected } from './Connected'
import { SwitchChain } from './SwitchChain'
Expand All @@ -20,7 +20,6 @@ export const Wallet = ({
}: WalletProps) => {
const { address, chainId: accountChainId, addresses = [] } = useAccount()
const { switchChain } = useSwitchChain()
const { reconnect } = useReconnect()

const isServer = typeof document === 'undefined'

Expand All @@ -31,10 +30,7 @@ export const Wallet = ({
// Wallet disconnected
if (address == null || addresses.length === 0) {
return (
<WalletDisconnected
onDisconnect={onDisconnect}
onReconnect={() => reconnect()}
>
<WalletDisconnected>
<Account>{pilotAddress}</Account>
</WalletDisconnected>
)
Expand Down
26 changes: 10 additions & 16 deletions deployables/app/app/components/wallet/WalletDisconnected.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import { SecondaryButton, Warning } from '@zodiac/ui'
import type { PropsWithChildren } from 'react'
import { LaunchConnectKit } from './LaunchConnectKit'
import { Section } from './Section'

type WalletDisconnectedProps = PropsWithChildren<{
onReconnect: () => void
onDisconnect: () => void
}>
type WalletDisconnectedProps = PropsWithChildren

export const WalletDisconnected = ({
children,
onReconnect,
onDisconnect,
}: WalletDisconnectedProps) => (
export const WalletDisconnected = ({ children }: WalletDisconnectedProps) => (
<Section>
{children}

Expand All @@ -21,13 +15,13 @@ export const WalletDisconnected = ({
</Warning>

<Section.Actions>
<SecondaryButton fluid onClick={onReconnect}>
Connect
</SecondaryButton>

<SecondaryButton fluid onClick={onDisconnect}>
Disconnect
</SecondaryButton>
<LaunchConnectKit>
{({ show }) => (
<SecondaryButton fluid onClick={show}>
Connect wallet
</SecondaryButton>
)}
</LaunchConnectKit>
</Section.Actions>
</Section>
)
2 changes: 1 addition & 1 deletion deployables/app/app/components/wallet/WrongAccount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const WrongAccount = ({ children, onDisconnect }: WrongAccountProps) => (
<Section>
{children}

<Warning title="Account is not connected">
<Warning title="Wallet is set to a different account">
Switch your wallet to this account in order to use Pilot.
</Warning>

Expand Down
12 changes: 9 additions & 3 deletions deployables/app/app/routes/submit.$route.$transactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
type ExecutionPlan,
type ExecutionState,
} from 'ser-kit'
import { useConnectorClient } from 'wagmi'
import { useAccount, useConnectorClient } from 'wagmi'
import type { Route } from './+types/submit.$route.$transactions'

export const loader = async ({ params }: Route.LoaderArgs) => {
Expand Down Expand Up @@ -62,14 +62,20 @@ const SubmitPage = ({
export default SubmitPage

const SubmitTransaction = () => {
const { plan, chainId, avatar } = useLoaderData<typeof loader>()
const { plan, chainId, avatar, initiator } = useLoaderData<typeof loader>()
const walletAccount = useAccount()
const { data: connectorClient } = useConnectorClient()
const [submitPending, setSubmitPending] = useState(false)

return (
<PrimaryButton
fluid
disabled={connectorClient == null || submitPending}
disabled={
walletAccount.chainId !== chainId ||
walletAccount.address?.toLowerCase() !== initiator ||
connectorClient == null ||
submitPending
}
onClick={async () => {
invariant(connectorClient != null, 'Client must be ready')

Expand Down
19 changes: 3 additions & 16 deletions deployables/app/e2e/accountHandling/lockedAccount.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,12 @@ test.describe('Locked account', () => {
await connectWallet(page, account)
await lockWallet()

await page.getByRole('button', { name: 'Connect', exact: true }).click()
await page
.getByRole('button', { name: 'Connect wallet', exact: true })
.click()

await expect(
page.getByRole('textbox', { name: 'Pilot Account' }),
).toHaveValue(account)
})

test('it is possible to disconnect a locked account', async ({ page }) => {
const { lockWallet } = await mockWeb3(page)

await page.goto('/new-route')

await connectWallet(page)
await lockWallet()

await page.getByRole('button', { name: 'Disconnect' }).click()

await expect(
page.getByRole('button', { name: 'Connect wallet' }),
).toBeInViewport()
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ test.describe('Account unavailable', () => {

await expect(
page.getByRole('alert', {
name: `Account is not connected`,
name: `Wallet is set to a different account`,
}),
).toHaveAccessibleDescription(
'Switch your wallet to this account in order to use Pilot.',
Expand Down

0 comments on commit 103f256

Please sign in to comment.