Skip to content

Commit

Permalink
refactor migrate util into persistOptions util (#1523)
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-schrammel authored and magiziz committed Apr 30, 2024
1 parent f196d00 commit 067916a
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 75 deletions.
10 changes: 5 additions & 5 deletions src/core/state/favorites/index.ts
Expand Up @@ -43,7 +43,7 @@ import {
} from '~/core/references';
import { AddressOrEth } from '~/core/types/assets';
import { ChainId } from '~/core/types/chains';
import { migrate } from '~/core/utils/migrate';
import { persistOptions } from '~/core/utils/persistOptions';

import { createStore } from '../internal/createStore';

Expand Down Expand Up @@ -149,10 +149,10 @@ export const favoritesStore = createStore<FavoritesState>(
},
}),
{
persist: {
persist: persistOptions({
name: 'favorites',
version: 4,
migrate: migrate(
migrations: [
// version 1 didn't need a migration
(state: FavoritesState) => state,
// version 2 added avalanche
Expand All @@ -164,8 +164,8 @@ export const favoritesStore = createStore<FavoritesState>(
// version 4 added degen
(state) =>
mergeNewOfficiallySupportedChainsState(state, [ChainId.degen]),
),
},
],
}),
},
);

Expand Down
59 changes: 37 additions & 22 deletions src/core/state/rainbowChains/index.ts
Expand Up @@ -8,7 +8,7 @@ import {
chainHardhat,
chainHardhatOptimism,
} from '~/core/types/chains';
import { migrate } from '~/core/utils/migrate';
import { persistOptions } from '~/core/utils/persistOptions';

import { createStore } from '../internal/createStore';

Expand Down Expand Up @@ -226,32 +226,42 @@ export const rainbowChainsStore = createStore<RainbowChainsState>(
},
}),
{
persist: {
persist: persistOptions({
name: 'rainbowChains',
version: 7,
migrate: migrate(
version: 8,
migrations: [
// v1 didn't need a migration
function v1(s: RainbowChainsState) {
return s;
},

// version 2 added support for Avalanche and Avalanche Fuji
(state) =>
mergeNewOfficiallySupportedChainsState(state, [
function v2(state) {
return mergeNewOfficiallySupportedChainsState(state, [
ChainId.avalanche,
ChainId.avalancheFuji,
]),
// version 2 added support for Blast
(state: RainbowChainsState) =>
mergeNewOfficiallySupportedChainsState(state, [
ChainId.avalanche,
ChainId.avalancheFuji,
]),
(state) =>
removeCustomRPC({
]);
},

// version 3 added support for Blast
function v3(state) {
return mergeNewOfficiallySupportedChainsState(state, [ChainId.blast]);
},

function v4(state) {
return removeCustomRPC({
state,
rpcUrl: 'https://rpc.zora.co',
rainbowChains: state.rainbowChains,
}),
});
},

// version 5 added support for Degen
(state: RainbowChainsState) =>
mergeNewOfficiallySupportedChainsState(state, [ChainId.degen]),
(state: RainbowChainsState) => {
function v5(state) {
return mergeNewOfficiallySupportedChainsState(state, [ChainId.degen]);
},

function v6(state) {
if (
!state.rainbowChains[zora.id] ||
state.rainbowChains[zora.id]?.chains.length === 0
Expand All @@ -260,7 +270,12 @@ export const rainbowChainsStore = createStore<RainbowChainsState>(
}
return state;
},
(state: RainbowChainsState) => {

function v7(state) {
return state;
},

function v8(state) {
if (
!state.rainbowChains[chainDegen.id] ||
state.rainbowChains[chainDegen.id]?.chains.length === 0
Expand All @@ -269,8 +284,8 @@ export const rainbowChainsStore = createStore<RainbowChainsState>(
}
return state;
},
),
},
],
}),
},
);

Expand Down
47 changes: 0 additions & 47 deletions src/core/utils/migrate.ts

This file was deleted.

125 changes: 125 additions & 0 deletions src/core/utils/persistOptions.ts
@@ -0,0 +1,125 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { PersistOptions } from 'zustand/middleware';

type Opts<T, Migrations> = PersistOptions<T> & {
version: number;
migrations: Migrations;
};

type R<T> = PersistOptions<T> & {
version: number;
migrate: (persistedState: unknown, version: number) => T;
};

interface PersistOptionsWithMigrations {
<Final>(opts: Opts<Final, [(s: any) => Final]>): R<Final>;
<Final, A>(opts: Opts<Final, [(s: any) => A, (s: A) => Final]>): R<Final>;
<Final, A, B>(
opts: Opts<Final, [(s: any) => A, (s: A) => B, (s: B) => Final]>,
): R<Final>;
<Final, A, B, C>(
opts: Opts<
Final,
[(s: any) => A, (s: A) => B, (s: B) => C, (s: C) => Final]
>,
): R<Final>;
<Final, A, B, C, D>(
opts: Opts<
Final,
[(s: any) => A, (s: A) => B, (s: B) => C, (s: C) => D, (s: D) => Final]
>,
): R<Final>;
<Final, A, B, C, D, E>(
opts: Opts<
Final,
[
(s: any) => A,
(s: A) => B,
(s: B) => C,
(s: C) => D,
(s: D) => E,
(s: E) => Final,
]
>,
): R<Final>;
<Final, A, B, C, D, E, F>(
opts: Opts<
Final,
[
(s: any) => A,
(s: A) => B,
(s: B) => C,
(s: C) => D,
(s: D) => E,
(s: E) => F,
(s: F) => Final,
]
>,
): R<Final>;
<Final, A, B, C, D, E, F, G>(
opts: Opts<
Final,
[
(s: any) => A,
(s: A) => B,
(s: B) => C,
(s: C) => D,
(s: D) => E,
(s: E) => F,
(s: F) => G,
(s: G) => Final,
]
>,
): R<Final>;
<Final, A, B, C, D, E, F, G, H>(
opts: Opts<
Final,
[
(s: any) => A,
(s: A) => B,
(s: B) => C,
(s: C) => D,
(s: D) => E,
(s: E) => F,
(s: F) => G,
(s: G) => H,
(s: H) => Final,
]
>,
): R<Final>;

// if you need more migrations, add more overloads here
}

/**
* Migrate a persisted state through a series of migrations, piping the result of each migration to the next.
*
* for example if user has persisted state from **version 1** and we are now at **version 3**, this will migrate the state from version **1** to **2** and then to **3**
* - migrations must be in order
* - zustand persister version must be an integer
*/
export const persistOptions: PersistOptionsWithMigrations = <TState>({
version: storeVersion,
migrations,
...persistOptions
}: PersistOptions<TState> & {
version: number;
migrations: ((s: unknown) => unknown)[];
}) => {
if (migrations && migrations.length !== storeVersion) {
throw new Error(`
!! Review the migrations !!
(store name: ${persistOptions.name})
`);
}

return {
version: storeVersion,
migrate: (persistedState: unknown, userVersion: number) =>
migrations
.toSpliced(0, userVersion) // remove migration before user version, as they should be already applied
.reduce((acc, fn) => fn(acc), persistedState),
...persistOptions,
};
};
2 changes: 1 addition & 1 deletion src/core/utils/userChains.ts
Expand Up @@ -80,7 +80,7 @@ export const chainLabelMap: Record<
[ChainId.zora]: [ChainNameDisplay[zoraSepolia.id]],
[ChainId.avalanche]: [ChainNameDisplay[avalancheFuji.id]],
[ChainId.blast]: [ChainNameDisplay[chainBlastSepolia.id]],
[ChainId.degen]: [ChainNameDisplay[chainDegen.id]],
[ChainId.degen]: [],
};

export const sortNetworks = (order: ChainId[], chains: Chain[]) => {
Expand Down

0 comments on commit 067916a

Please sign in to comment.