diff --git a/e2e/src/utils/search.utils.ts b/e2e/src/utils/search.utils.ts index b2306cb91..f0b86e3e5 100644 --- a/e2e/src/utils/search.utils.ts +++ b/e2e/src/utils/search.utils.ts @@ -18,7 +18,7 @@ export const findElement = async ( }; export const findElementBySelectors = async (selectors: string, timeout = MEDIUM_TIMEOUT, errorTitle?: string) => { - const element = await BrowserContext.page.waitForSelector(selectors, { timeout }).catch(error => { + const element = await BrowserContext.page.waitForSelector(selectors, { visible: true, timeout }).catch(error => { if (errorTitle && error instanceof Error) { error.message = `${errorTitle}\n` + error.message; } diff --git a/src/app/atoms/AssetField.tsx b/src/app/atoms/AssetField.tsx index 612ac4876..d98dc2108 100644 --- a/src/app/atoms/AssetField.tsx +++ b/src/app/atoms/AssetField.tsx @@ -4,14 +4,14 @@ import BigNumber from 'bignumber.js'; import { FormField } from 'app/atoms'; -type AssetFieldProps = Omit, 'onChange'> & { +interface AssetFieldProps extends Omit, 'onChange'> { value?: number | string; min?: number; max?: number; assetSymbol?: ReactNode; assetDecimals?: number; onChange?: (v?: string) => void; -}; +} const AssetField = forwardRef( ( diff --git a/src/app/atoms/FormField.tsx b/src/app/atoms/FormField.tsx index bb3a14152..3d3e17a22 100644 --- a/src/app/atoms/FormField.tsx +++ b/src/app/atoms/FormField.tsx @@ -218,10 +218,10 @@ const ExtraInner: React.FC = ({ useDefaultWrapper, innerCompone
- {innerComponent} +
{innerComponent}
); return <>{innerComponent}; diff --git a/src/app/store/collectibles-metadata/state.ts b/src/app/store/collectibles-metadata/state.ts index 04247b276..97cb6d36f 100644 --- a/src/app/store/collectibles-metadata/state.ts +++ b/src/app/store/collectibles-metadata/state.ts @@ -1,3 +1,5 @@ +import { cloneDeep } from 'lodash'; + import type { TokenMetadata } from 'lib/metadata'; /** @@ -16,6 +18,9 @@ export const collectiblesMetadataInitialState: SliceState = { isLoading: false }; +/** Cannot use initial value during migrations - object is frozen & forbids mutations. */ +export const collectiblesMetadataInitialStateClone = cloneDeep(collectiblesMetadataInitialState); + export const sanitizeCollectiblesMetadataForDevTools = (state: S): S => ({ ...state, records: Array.from(state.records.values()) as unknown as MetadataMap diff --git a/src/app/store/index.ts b/src/app/store/index.ts index d9b930918..e26789658 100644 --- a/src/app/store/index.ts +++ b/src/app/store/index.ts @@ -12,13 +12,15 @@ import { epicMiddleware, rootEpic } from './root-state.epics'; import { rootReducer } from './root-state.reducer'; import type { RootState } from './root-state.type'; -const persistConfigBlacklist: (keyof RootState)[] = [ - 'buyWithCreditCard', - 'collectibles', - 'assets', - 'collectiblesMetadata' +export const SLICES_BLACKLIST = [ + 'buyWithCreditCard' as const, + 'collectibles' as const, + 'assets' as const, + 'collectiblesMetadata' as const ]; +const persistConfigBlacklist: (keyof RootState)[] = SLICES_BLACKLIST; + const persistedReducer = persistReducer( { key: 'temple-root', diff --git a/src/app/store/migrations.ts b/src/app/store/migrations.ts index 208c029c2..b87be8a3d 100644 --- a/src/app/store/migrations.ts +++ b/src/app/store/migrations.ts @@ -3,9 +3,18 @@ import type { MigrationManifest, PersistedState } from 'redux-persist'; import { toTokenSlug } from 'lib/assets'; import { isCollectible } from 'lib/metadata'; +import { collectiblesMetadataInitialStateClone } from './collectibles-metadata/state'; import type { RootState } from './root-state.type'; -type TypedPersistedRootState = Exclude & RootState; +import type { SLICES_BLACKLIST } from './index'; + +type MakePropertiesOptional = { + [P in keyof T]: P extends K ? T[P] | undefined : T[P]; +}; + +/** Blacklisted slices are not rehydrated */ +type TypedPersistedRootState = Exclude & + MakePropertiesOptional; export const MIGRATIONS: MigrationManifest = { '2': (persistedState: PersistedState) => { @@ -13,6 +22,11 @@ export const MIGRATIONS: MigrationManifest = { const typedPersistedState = persistedState as TypedPersistedRootState; const allTokensMetadata = typedPersistedState.tokensMetadata.metadataRecord; + // `collectiblesMetadata` slice data is absent. Setting initial value here. + // It is safe as it is blacklisted & won't be persisted in this (root) slice. + // @ts-expect-error // Due to the absence of `_persist` property yet + const collectiblesMetadata = (typedPersistedState.collectiblesMetadata = collectiblesMetadataInitialStateClone); + for (const slug of Object.keys(allTokensMetadata)) { const metadata = allTokensMetadata[slug]; if (!metadata) { @@ -34,7 +48,7 @@ export const MIGRATIONS: MigrationManifest = { const newSlug = toTokenSlug(metadata.address, tokenId); if (isCollectible(metadata)) { - typedPersistedState.collectiblesMetadata.records.set(newSlug, { + collectiblesMetadata.records.set(newSlug, { ...metadata, id: tokenId }); diff --git a/src/app/templates/AssetSelect.tsx b/src/app/templates/AssetSelect.tsx index 77c78b249..9c742e3e4 100644 --- a/src/app/templates/AssetSelect.tsx +++ b/src/app/templates/AssetSelect.tsx @@ -93,7 +93,7 @@ const AssetSelectTitle: FC = () => ( ); -const AssetFieldContent: FC<{ slug: string } & TestIDProperty> = ({ slug, testID }) => { +const AssetFieldContent = memo<{ slug: string } & TestIDProperty>(({ slug, testID }) => { const account = useAccount(); const metadata = useAssetMetadata(slug); @@ -125,7 +125,7 @@ const AssetFieldContent: FC<{ slug: string } & TestIDProperty> = ({ slug, testID ); -}; +}); const AssetOptionContent: FC<{ slug: string; selected: boolean }> = ({ slug, selected }) => (
theme('spacing'), minHeight: theme => theme('height'),