/ common / features / configureStore.ts
configureStore.ts
  1  import { applyMiddleware, createStore, Store } from 'redux';
  2  import createSagaMiddleware from 'redux-saga';
  3  import { routerMiddleware } from 'react-router-redux';
  4  import { composeWithDevTools } from 'redux-devtools-extension';
  5  import { createLogger } from 'redux-logger';
  6  import throttle from 'lodash/throttle';
  7  
  8  import { loadStatePropertyOrEmptyObject, saveState } from 'utils/localStorage';
  9  import { gasPriceToBase } from 'libs/units';
 10  import RootReducer, { AppState } from './reducers';
 11  import sagas from './sagas';
 12  import { TransactionState } from './transaction/types';
 13  import { INITIAL_STATE as transactionInitialState } from './transaction/reducer';
 14  import { SwapState } from './swap/types';
 15  import { INITIAL_STATE as initialSwapState } from './swap/reducer';
 16  import { AddressBookState } from './addressBook/types';
 17  import { TransactionsState } from './transactions/types';
 18  import { INITIAL_STATE as initialTransactionsState } from './transactions/reducer';
 19  import { WalletState } from './wallet/types';
 20  import { INITIAL_STATE as initialWalletState } from './wallet/reducer';
 21  import {
 22    rehydrateConfigAndCustomTokenState,
 23    getConfigAndCustomTokensStateToSubscribe
 24  } from './configAndTokens';
 25  import rehydrateAddressBook from './rehydrateAddressBook';
 26  
 27  export default function configureStore() {
 28    const logger = createLogger({
 29      collapsed: true
 30    });
 31    const sagaMiddleware = createSagaMiddleware();
 32    let middleware;
 33    let store: Store<AppState>;
 34  
 35    if (process.env.NODE_ENV !== 'production') {
 36      middleware = composeWithDevTools(
 37        applyMiddleware(sagaMiddleware, logger, routerMiddleware(history as any))
 38      );
 39    } else {
 40      middleware = applyMiddleware(sagaMiddleware, routerMiddleware(history as any));
 41    }
 42  
 43    // ONLY LOAD SWAP STATE FROM LOCAL STORAGE IF STEP WAS 3
 44    const localSwapState = loadStatePropertyOrEmptyObject<SwapState>('swap');
 45    const swapState =
 46      localSwapState && localSwapState.step === 3
 47        ? {
 48            ...initialSwapState,
 49            ...localSwapState
 50          }
 51        : { ...initialSwapState };
 52  
 53    const savedTransactionState = loadStatePropertyOrEmptyObject<TransactionState>('transaction');
 54    const savedTransactionsState = loadStatePropertyOrEmptyObject<TransactionsState>('transactions');
 55    const savedAddressBook = loadStatePropertyOrEmptyObject<AddressBookState>('addressBook');
 56    const savedWalletState = loadStatePropertyOrEmptyObject<WalletState>('wallet');
 57  
 58    const persistedInitialState: Partial<AppState> = {
 59      transaction: {
 60        ...transactionInitialState,
 61        fields: {
 62          ...transactionInitialState.fields,
 63          gasPrice:
 64            savedTransactionState && savedTransactionState.fields.gasPrice
 65              ? {
 66                  raw: savedTransactionState.fields.gasPrice.raw,
 67                  value: gasPriceToBase(+savedTransactionState.fields.gasPrice.raw)
 68                }
 69              : transactionInitialState.fields.gasPrice
 70        }
 71      },
 72      swap: swapState,
 73      transactions: {
 74        ...initialTransactionsState,
 75        ...savedTransactionsState
 76      },
 77      addressBook: rehydrateAddressBook(savedAddressBook),
 78      wallet: {
 79        ...initialWalletState,
 80        ...savedWalletState
 81      },
 82      ...rehydrateConfigAndCustomTokenState()
 83    };
 84  
 85    store = createStore<AppState>(RootReducer, persistedInitialState as any, middleware);
 86  
 87    // Add all of the sagas to the middleware
 88    Object.keys(sagas).forEach((saga: keyof typeof sagas) => {
 89      sagaMiddleware.run(sagas[saga]);
 90    });
 91  
 92    store.subscribe(
 93      throttle(() => {
 94        const state: AppState = store.getState();
 95  
 96        saveState({
 97          transaction: {
 98            fields: {
 99              gasPrice: state.transaction.fields.gasPrice
100            }
101          },
102          swap: {
103            ...state.swap,
104            options: {
105              byId: {},
106              allIds: []
107            },
108            bityRates: {
109              byId: {},
110              allIds: []
111            },
112            shapeshiftRates: {
113              byId: {},
114              allIds: []
115            }
116          },
117          transactions: {
118            recent: state.transactions.recent
119          },
120          addressBook: state.addressBook,
121          wallet: {
122            recentAddresses: state.wallet.recentAddresses
123          },
124          ...getConfigAndCustomTokensStateToSubscribe(state)
125        });
126      }, 50)
127    );
128  
129    return store;
130  }