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

feat: allow adding networks without invalidating local-storage #5134

Merged
merged 2 commits into from
Nov 27, 2024

Conversation

anxolin
Copy link
Contributor

@anxolin anxolin commented Nov 26, 2024

Summary

Make CoW Swap more resilient for run-time errors when we introduce new networks.

Motivation

Every addition of a new chain makes us increase the version all the local storages that have some state per network.
This is because a lot of state is model as Record<SupportedChainId, MyState>>, because SupportedChainId type is changes with the addition of a network, we need to version the local storage key.

This makes all users to loose their state or settings.

What is worse is that, updating the version is something super easy to forget to do, and if you forget to do it for one of the states it will easily lead to a hard crash of the app that is:

  • hard to debug
  • hard to notice (only users with old states will have the issue)

The error comes from assuming the type of the deserialised state is the one defined in the app, which contains a state for a newly added chain, however because the object was serialised in the past, the state for that chain is undefined.

Typescript will be unable to detect at compile time if you forgot to handle the undefined case. This will lead to run-time errors.

Solution

Basically assume that the state can be undefined for all states that follow the pattern Record<SupportedChainId, MyState>.

Because this pattern is very common, and we have a lot of persisted states by network, I defined a new helper type which makes the definition of the state simpler.

type PersistentStateByChain<T> = Record<SupportedChainId, T | undefined>

This way, we can turn this state:
Record<SupportedChainId, CustomHooksState>>

into:
PersistentStateByChain<CustomHooksState>>

And it will already assume that some chain might be un-initialised

Test

This PR doesn't change any logic. So everything should work as before.

Its a bit sensitive PR because it touches the state logic of many critical parts of the app, such as balances, token lists, etc
So probably good to test all flows.

If we want to stress test this PR, we could go to the local storage and delete the KEY for one chain we have.
For example:

  • For example, go to you local storage, and replace the content of allTokenListsInfoAtom:v4 with {}
  • You can try also to delete only one network instead of all of them, and see how it doesn't crash to use other networks, nor doesn't crash for the deleted network.
    • For example, for key hooksStoreAtom:v3 we can leave only mainnet {"1":{}}

Copy link

vercel bot commented Nov 26, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
cosmos ✅ Ready (Inspect) Visit Preview Nov 26, 2024 4:57pm
cowfi ✅ Ready (Inspect) Visit Preview Nov 26, 2024 4:57pm
explorer-dev ✅ Ready (Inspect) Visit Preview Nov 26, 2024 4:57pm
swap-dev ✅ Ready (Inspect) Visit Preview Nov 26, 2024 4:57pm
widget-configurator ✅ Ready (Inspect) Visit Preview Nov 26, 2024 4:57pm

Copy link
Contributor

@elena-zh elena-zh left a comment

Choose a reason for hiding this comment

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

Looks good to me!

Copy link
Collaborator

@shoom3301 shoom3301 left a comment

Choose a reason for hiding this comment

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

Great fix! Thank you

@shoom3301 shoom3301 merged commit 995b4c0 into develop Nov 27, 2024
10 of 12 checks passed
@shoom3301 shoom3301 deleted the storage-resiliance-for-adding-networks branch November 27, 2024 05:46
@github-actions github-actions bot locked and limited conversation to collaborators Nov 27, 2024
Copy link
Collaborator

@alfetopito alfetopito left a comment

Choose a reason for hiding this comment

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

Thank you, I completely missed this 🙈

Comment on lines +6 to +7
export function useUnsupportedTokens(): UnsupportedTokensState {
return useAtomValue(currentUnsupportedTokensAtom) || {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Given the recent issue returning a new array on every render, shouldn't this also have a stable empty value declared outside of the hook?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants