Skip to content

Commit

Permalink
fix: #4150
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm committed Jul 17, 2024
1 parent 8d81df5 commit 5bc8c88
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/pink-years-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wagmi/core": patch
---

Fixed reconnection when `status` is defined.
53 changes: 51 additions & 2 deletions packages/core/src/actions/reconnect.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { accounts, config } from '@wagmi/test'
import { afterEach, expect, test } from 'vitest'
import { accounts, config, mainnet } from '@wagmi/test'
import { afterEach, expect, test, vi } from 'vitest'
import { http } from 'viem'

import { mock } from '../connectors/mock.js'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
import { reconnect } from './reconnect.js'
import { createStorage } from '../createStorage.js'
import { createConfig } from '../createConfig.js'

const connector = config._internal.connectors.setup(
mock({
Expand Down Expand Up @@ -68,3 +71,49 @@ test("behavior: doesn't reconnect if already reconnecting", async () => {
).resolves.toStrictEqual([])
config.setState((x) => ({ ...x, status: previousStatus }))
})

test('behavior: recovers from invalid state', async () => {
const state = {
'wagmi.store': JSON.stringify({
state: {
status: 'connected', // <-- invalid - `status` should not be kept in storage
chainId: 1,
current: '983b8aca245',
},
version: Number.NaN, // mocked version is `'x.y.z'`, which will get interpreted as `NaN`
}),
} as Record<string, string>
Object.defineProperty(window, 'localStorage', {
value: {
getItem: vi.fn((key) => state[key] ?? null),
removeItem: vi.fn((key) => state.delete?.[key]),
setItem: vi.fn((key, value) => {
state[key] = value
}),
},
writable: true,
})

const storage = createStorage<{ store: object }>({
storage: window.localStorage,
})

const config = createConfig({
chains: [mainnet],
storage,
transports: {
[mainnet.id]: http(),
},
})

await reconnect(config, { connectors: [connector] })

expect(config.state).toMatchInlineSnapshot(`
{
"chainId": 1,
"connections": Map {},
"current": null,
"status": "disconnected",
}
`)
})
17 changes: 15 additions & 2 deletions packages/core/src/createConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export function createConfig<
const prefix = '0.0.0-canary-'
if (version.startsWith(prefix))
currentVersion = Number.parseInt(version.replace(prefix, ''))
// use package major version to version store
else currentVersion = Number.parseInt(version.split('.')[0] ?? '0')

const store = createStore(
Expand Down Expand Up @@ -243,9 +244,21 @@ export function createConfig<
} as unknown as PartializedState['connections'],
chainId: state.chainId,
current: state.current,
status: state.status,
} satisfies PartializedState
},
merge(persistedState, currentState) {
// `status` should not be persisted as it messes with reconnection
if (
typeof persistedState === 'object' &&
persistedState &&
'status' in persistedState
)
delete persistedState.status
return {
...currentState,
...(persistedState as object),
}
},
skipHydration: ssr,
storage: storage as Storage<Record<string, unknown>>,
version: currentVersion,
Expand Down Expand Up @@ -550,7 +563,7 @@ export type State<
}

export type PartializedState = Compute<
ExactPartial<Pick<State, 'chainId' | 'connections' | 'current' | 'status'>>
ExactPartial<Pick<State, 'chainId' | 'connections' | 'current'>>
>

export type Connection = {
Expand Down

0 comments on commit 5bc8c88

Please sign in to comment.