import { getDerivationPath } from '@mycrypto/wallets' ; import { Reducer } from '@reduxjs/toolkit' ; import { createMigrate , createTransform , FLUSH , PAUSE , PERSIST , PersistConfig , persistReducer , PURGE , REGISTER , REHYDRATE , StateReconciler , Transform , TransformInbound , TransformOutbound } from 'redux-persist' ; import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2' ; import storage from 'redux-persist/lib/storage' ; import { OmitByValue , ValuesType } from 'utility-types' ; import { defaultContacts } from '@database' ; import { DataStore , LocalStorage , LSKeys , NetworkId , TUuid } from '@types' ; import { arrayToObj , IS_DEV } from '@utils' ; import { dissoc , flatten , pipe , propEq , reject , values } from '@vendor' ; import { generateCustomDPath , mergeAssets , mergeNetworks } from './helpers' ; export const REDUX_PERSIST_ACTION_TYPES = [ FLUSH , REHYDRATE , PAUSE , PERSIST , PURGE , REGISTER ] ; param slice param key const fromReduxStore = ( slice , key ) => { switch ( key ) { case LSKeys . ACCOUNTS : case LSKeys . ADDRESS_BOOK : case LSKeys . CONTRACTS : case LSKeys . ASSETS : case LSKeys . NOTIFICATIONS : case LSKeys . USER_ACTIONS : { return arrayToObj < TUuid > ( 'uuid' ) ( slice ) ; } case LSKeys . NETWORKS : { return arrayToObj < NetworkId > ( 'id' ) ( slice ) ; } case LSKeys . SETTINGS : default : return slice ; } } ; param slice param key const fromPersistenceLayer = ( slice , key ) => { switch ( key ) { case LSKeys . ACCOUNTS : case LSKeys . ADDRESS_BOOK : case LSKeys . CONTRACTS : case LSKeys . ASSETS : case LSKeys . NOTIFICATIONS : case LSKeys . USER_ACTIONS : case LSKeys . NETWORKS : return Object . values ( slice ) ; case LSKeys . SETTINGS : default : return slice ; } } ; const transform = createTransform ( fromReduxStore , fromPersistenceLayer ) ; param inboundState param originalState param reducedState param config const customReconciler = ( inboundState , originalState , ... rest ) => { const mergeByUuid = pipe ( arrayToObj < TUuid > ( 'uuid' ) , values , flatten ) ; const mergedInboundState = { ... inboundState , [ LSKeys . ASSETS ] : mergeAssets ( inboundState . assets , originalState . assets ) , [ LSKeys . CONTRACTS ] : mergeByUuid ( [ ... inboundState . contracts , ... originalState . contracts ] ) , [ LSKeys . NETWORKS ] : mergeNetworks ( inboundState . networks , originalState . networks ) } ; return autoMergeLevel2 ( mergedInboundState , originalState , ... rest ) ; } ; param slice const customDeserializer = ( slice ) => { if ( typeof slice === 'string' ) { if ( slice === 'v2.0.0' || slice === 'v1.0.0' || slice === 'v1.1.0' || slice === '' ) return slice ; return JSON . parse ( slice ) ; } else { return slice ; } } ; export const migrations = { 2 : ( state ) => { return { ... state , networks : state . networks . map ( ( { autoNode , ... n } ) => ( { ... n , selectedNode : n . selectedNode === autoNode ? undefined : n . selectedNode } ) ) } ; } , 3 : ( state ) => { const MYC_DONATE_CONTACT = values ( defaultContacts ) [ 0 ] ; return { ... state , [ LSKeys . ADDRESS_BOOK ] : [ ... reject ( propEq ( 'uuid' , MYC_DONATE_CONTACT . uuid ) , state [ LSKeys . ADDRESS_BOOK ] ) , MYC_DONATE_CONTACT ] } ; } , 4 : ( state ) => { return { ... state , rates : state . rates ? state . rates : state . settings . rates ? state . settings . rates : [ ] , trackedAssets : state . trackedAssets ? state . trackedAssets : [ ] , settings : dissoc ( 'rates' , state . settings ) } ; } , 5 : ( state ) => { return { ... state , settings : dissoc ( 'inactivityTimer' , state . settings ) } ; } , 6 : ( state ) => { return { ... state , accounts : state . accounts . map ( ( { dPath , ... account } ) => { if ( ! dPath ) { return account ; } const result = getDerivationPath ( dPath ) ; const [ path , index ] = result ?? generateCustomDPath ( dPath ) ; return { ... account , path , index } ; } ) } ; } } ; export const migrate = createMigrate ( migrations , { debug : IS_DEV } ) ; export const APP_PERSIST_CONFIG = { version : 6 , key : 'Storage' , keyPrefix : 'MYC_' , storage , blacklist : [ ] , stateReconciler : customReconciler , transforms : [ transform ] , deserialize : customDeserializer , debug : IS_DEV , migrate } ; export const createPersistReducer = ( reducer ) => persistReducer ( APP_PERSIST_CONFIG , reducer ) ;