import { SetBalanceFullfilledAction } from 'actions/wallet/actionTypes'; import { SetTokenBalancesFulfilledAction, SetWalletAction, WalletAction, SetWalletConfigAction, SetWalletPendingAction, TypeKeys, SetTokenBalanceFulfilledAction } from 'actions/wallet'; import { TokenValue } from 'libs/units'; import { IWallet, Balance, WalletConfig } from 'libs/wallet'; import { translateRaw } from 'translations'; export interface State { inst?: IWallet | null; config?: WalletConfig | null; // in ETH balance: Balance; tokens: { [key: string]: { balance: TokenValue; error: string | null; }; }; isWalletPending: boolean; isTokensLoading: boolean; isPasswordPending: boolean; tokensError: string | null; hasSavedWalletTokens: boolean; recentAddresses: string[]; } export const INITIAL_STATE: State = { inst: null, config: null, balance: { isPending: false, wei: null }, tokens: {}, isWalletPending: false, isPasswordPending: false, isTokensLoading: false, tokensError: null, hasSavedWalletTokens: true, recentAddresses: [] }; export const RECENT_ADDRESS_LIMIT = 10; function addRecentAddress(addresses: string[], newWallet: IWallet | null) { if (!newWallet) { return addresses; } // Push new address onto the front const newAddresses = [newWallet.getAddressString(), ...addresses]; // Dedupe addresses, limit length return newAddresses .filter((addr, idx) => newAddresses.indexOf(addr) === idx) .splice(0, RECENT_ADDRESS_LIMIT); } function setWallet(state: State, action: SetWalletAction): State { return { ...state, inst: action.payload, config: INITIAL_STATE.config, balance: INITIAL_STATE.balance, tokens: INITIAL_STATE.tokens, recentAddresses: addRecentAddress(state.recentAddresses, action.payload) }; } function setBalancePending(state: State): State { return { ...state, balance: { ...state.balance, isPending: true } }; } function setBalanceFullfilled(state: State, action: SetBalanceFullfilledAction): State { return { ...state, balance: { wei: action.payload, isPending: false } }; } function setBalanceRejected(state: State): State { return { ...state, balance: { ...state.balance, isPending: false } }; } function setWalletPending(state: State, action: SetWalletPendingAction): State { return { ...state, isWalletPending: action.payload }; } function setPasswordPending(state: State): State { return { ...state, isPasswordPending: true }; } function setTokenBalancesPending(state: State): State { return { ...state, tokens: {}, isTokensLoading: true, tokensError: null }; } function setTokenBalancePending(state: State): State { return { ...state, isTokensLoading: true, tokensError: null }; } function setTokenBalanceFufilled(state: State, action: SetTokenBalanceFulfilledAction): State { return { ...state, tokens: { ...state.tokens, ...action.payload }, isTokensLoading: false }; } function setTokenBalanceRejected(state: State): State { return { ...state, isTokensLoading: false, tokensError: translateRaw('SCAN_TOKENS_FAIL') }; } function setTokenBalancesFulfilled(state: State, action: SetTokenBalancesFulfilledAction): State { return { ...state, tokens: action.payload, isTokensLoading: false }; } function setTokenBalancesRejected(state: State): State { return { ...state, isTokensLoading: false, tokensError: translateRaw('SCAN_TOKENS_FAIL') }; } function scanWalletForTokens(state: State): State { return { ...state, hasSavedWalletTokens: false }; } function setWalletTokens(state: State): State { return { ...state, hasSavedWalletTokens: true }; } function setWalletConfig(state: State, action: SetWalletConfigAction): State { return { ...state, config: action.payload }; } function resetWallet(state: State): State { return { ...INITIAL_STATE, recentAddresses: state.recentAddresses }; } export function wallet(state: State = INITIAL_STATE, action: WalletAction): State { switch (action.type) { case TypeKeys.WALLET_SET: return setWallet(state, action); case TypeKeys.WALLET_RESET: return resetWallet(state); case TypeKeys.WALLET_SET_BALANCE_PENDING: return setBalancePending(state); case TypeKeys.WALLET_SET_BALANCE_FULFILLED: return setBalanceFullfilled(state, action); case TypeKeys.WALLET_SET_BALANCE_REJECTED: return setBalanceRejected(state); case TypeKeys.WALLET_SET_PENDING: return setWalletPending(state, action); case TypeKeys.WALLET_SET_TOKEN_BALANCES_PENDING: return setTokenBalancesPending(state); case TypeKeys.WALLET_SET_TOKEN_BALANCES_FULFILLED: return setTokenBalancesFulfilled(state, action); case TypeKeys.WALLET_SET_TOKEN_BALANCES_REJECTED: return setTokenBalancesRejected(state); case TypeKeys.WALLET_SET_TOKEN_BALANCE_PENDING: return setTokenBalancePending(state); case TypeKeys.WALLET_SET_TOKEN_BALANCE_FULFILLED: return setTokenBalanceFufilled(state, action); case TypeKeys.WALLET_SET_TOKEN_BALANCE_REJECTED: return setTokenBalanceRejected(state); case TypeKeys.WALLET_SCAN_WALLET_FOR_TOKENS: return scanWalletForTokens(state); case TypeKeys.WALLET_SET_WALLET_TOKENS: return setWalletTokens(state); case TypeKeys.WALLET_SET_CONFIG: return setWalletConfig(state, action); case TypeKeys.WALLET_SET_PASSWORD_PENDING: return setPasswordPending(state); default: return state; } }