Skip to content

Commit

Permalink
wip: useAccountState
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm committed Aug 9, 2023
1 parent 9173b47 commit bcc6c61
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 8 deletions.
5 changes: 3 additions & 2 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ function getSidebar() {
text: 'Community',
items: [
{ text: 'Contributing 🚧', link: '/react/contributing' },
{ text: 'Sponsors 🚧', link: '/react/sponsor' },
{ text: 'Sponsors 🚧', link: '/react/sponsors' },
],
},
],
Expand Down Expand Up @@ -403,6 +403,7 @@ function getSidebar() {
{
text: 'Actions 🚧',
collapsed: true,
link: '/core/actions',
items: [
{ text: 'connect', link: '/core/actions/connect' },
{ text: 'disconnect', link: '/core/actions/disconnect' },
Expand Down Expand Up @@ -529,7 +530,7 @@ function getSidebar() {
text: 'Community',
items: [
{ text: 'Contributing 🚧', link: '/core/contributing' },
{ text: 'Sponsors 🚧', link: '/core/sponsor' },
{ text: 'Sponsors 🚧', link: '/core/sponsors' },
],
},
],
Expand Down
1 change: 1 addition & 0 deletions docs/core/actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Actions
1 change: 1 addition & 0 deletions docs/react/connectors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Connectors
4 changes: 2 additions & 2 deletions packages/core/src/actions/getAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ export function getAccount(config: Config): GetAccountReturnType {
// Watcher

export type WatchAccountParameters = {
onChange(data: GetAccountReturnType): void
onChange(data: GetAccountReturnType, prevData: GetAccountReturnType): void
}

export type WatchAccountReturnType = () => void

/** https://wagmi.sh/core/actions/getAccount#watcher */
/** https://wagmi.sh/core/actions/getAccount#watchaccount */
export function watchAccount(
config: Config,
{ onChange }: WatchAccountParameters,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/actions/getBlockNumber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type WatchBlockNumberParameters<config extends Config = Config> =
export type WatchBlockNumberReturnType = viem_WatchBlockNumberReturnType

// TODO: wrap in viem's `observe` to avoid duplicate invocations.
/** https://wagmi.sh/core/actions/getBlockNumber#watcher */
/** https://wagmi.sh/core/actions/getBlockNumber#watchblocknumber */
export function watchBlockNumber<config extends Config>(
config: config,
parameters: WatchBlockNumberParameters<config>,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/actions/getChainId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export type WatchChainIdParameters<config extends Config = Config> = {

export type WatchChainIdReturnType = () => void

/** https://wagmi.sh/core/actions/getChainId#watcher */
/** https://wagmi.sh/core/actions/getChainId#watchchainid */
export function watchChainId<config extends Config>(
config: config,
parameters: WatchChainIdParameters<config>,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/actions/getConnections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type WatchConnectionsParameters = {

export type WatchConnectionsReturnType = () => void

/** https://wagmi.sh/core/actions/getConnections#watcher */
/** https://wagmi.sh/core/actions/getConnections#watchconnections */
export function watchConnections(
config: Config,
parameters: WatchConnectionsParameters,
Expand Down
4 changes: 3 additions & 1 deletion packages/react/src/hooks/useAccount.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { connect } from '@wagmi/core'
import { connect, disconnect } from '@wagmi/core'
import { config } from '@wagmi/test'
import { renderHook } from '@wagmi/test/react'
import { expect, test } from 'vitest'
Expand All @@ -16,4 +16,6 @@ test('default', async () => {

expect(result.current.address).toBeDefined()
expect(result.current.status).toEqual('connected')

await disconnect(config)
})
69 changes: 69 additions & 0 deletions packages/react/src/hooks/useAccountState.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { connect, createConfig, disconnect, http } from '@wagmi/core'
import { accounts, chain, testConnector } from '@wagmi/test'
import { createWrapper, renderHook, waitFor } from '@wagmi/test/react'
import { expect, test, vi } from 'vitest'

import { WagmiProvider } from '../context.js'
import { useAccountState } from './useAccountState.js'
import { useConnect } from './useConnect.js'
import { useDisconnect } from './useDisconnect.js'

test('behavior: connect and disconnect called once', async () => {
const onConnect = vi.fn()
const onDisconnect = vi.fn()

const { result } = renderHook(() => ({
useAccountState: useAccountState({ onConnect, onDisconnect }),
useConnect: useConnect(),
useDisconnect: useDisconnect(),
}))

result.current.useConnect.connect({
connector: result.current.useConnect.connectors[0]!,
})
await waitFor(() => expect(result.current.useConnect.isSuccess).toBeTruthy())

result.current.useConnect.connect({
connector: result.current.useConnect.connectors[0]!,
})
await waitFor(() => expect(result.current.useConnect.isSuccess).toBeTruthy())

result.current.useDisconnect.disconnect()
await waitFor(() =>
expect(result.current.useDisconnect.isSuccess).toBeTruthy(),
)
result.current.useDisconnect.disconnect()
await waitFor(() =>
expect(result.current.useDisconnect.isSuccess).toBeTruthy(),
)

expect(onConnect).toBeCalledTimes(1)
expect(onDisconnect).toBeCalledTimes(1)
})

test('behavior: connect called on reconnect', async () => {
const config = createConfig({
chains: [chain.mainnet],
connectors: [
testConnector({
accounts,
features: { reconnect: true },
}),
],
reconnectOnMount: true,
transports: { [chain.mainnet.id]: http() },
})

await connect(config, { connector: config.connectors[0]! })
const onConnect = vi.fn((data) => {
expect(data.isReconnected).toBeTruthy()
})

renderHook(() => useAccountState({ onConnect }), {
wrapper: createWrapper(WagmiProvider, { value: config }),
})

await waitFor(() => expect(onConnect).toBeCalledTimes(1))

await disconnect(config)
})
49 changes: 49 additions & 0 deletions packages/react/src/hooks/useAccountState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { type GetAccountReturnType, watchAccount } from '@wagmi/core'
import type { Evaluate } from '@wagmi/core/internal'

import { useConfig } from './useConfig.js'
import { useEffect } from 'react'

export type UseAccountStateParameters = {
onConnect?(
data: Evaluate<
Pick<
Extract<GetAccountReturnType, { status: 'connected' }>,
'address' | 'addresses' | 'chainId' | 'connector'
> & {
isReconnected: boolean
}
>,
): void
onDisconnect?(): void
}

/** https://wagmi.sh/react/hooks/useAccountState */
export function useAccountState(parameters: UseAccountStateParameters = {}) {
const { onConnect, onDisconnect } = parameters
const config = useConfig()

useEffect(() => {
return watchAccount(config, {
onChange(data, prevData) {
if (
(prevData.status === 'reconnecting' ||
(prevData.status === 'connecting' &&
prevData.address === undefined)) &&
data.status === 'connected'
) {
const { address, addresses, chainId, connector } = data
const isReconnected =
prevData.status === 'reconnecting' ||
// if `previousAccount.status` is `undefined`, the connector connected immediately.
prevData.status === undefined
onConnect?.({ address, addresses, chainId, connector, isReconnected })
} else if (
prevData.status === 'connected' &&
data.status === 'disconnected'
)
onDisconnect?.()
},
})
}, [config, onConnect, onDisconnect])
}
5 changes: 5 additions & 0 deletions packages/react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export { WagmiProviderNotFoundError } from './errors/context.js'

export { type UseAccountReturnType, useAccount } from './hooks/useAccount.js'

export {
type UseAccountStateParameters,
useAccountState,
} from './hooks/useAccountState.js'

export {
type UseBalanceParameters,
type UseBalanceReturnType,
Expand Down
10 changes: 10 additions & 0 deletions playgrounds/vite-react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
useAccount,
useAccountState,
useBalance,
useBlockNumber,
useChainId,
Expand All @@ -15,6 +16,15 @@ import {
import { optimism } from 'wagmi/chains'

function App() {
useAccountState({
onConnect(data) {
console.log('onConnect', data)
},
onDisconnect() {
console.log('onDisconnect')
},
})

return (
<>
<Account />
Expand Down

1 comment on commit bcc6c61

@vercel
Copy link

@vercel vercel bot commented on bcc6c61 Aug 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

wagmi-v2 – ./docs

wagmi-v2.vercel.app
wagmi-v2-git-alpha-wagmi-dev.vercel.app
wagmi-v2-wagmi-dev.vercel.app
alpha.wagmi.sh

Please sign in to comment.