<commit_before>import { createSelector } from 'reselect'
import get from 'lodash.get'
import { networks } from '@zap/utils/crypto'
import { grpcService } from 'workers'
import { initAddresses } from './address'
import { putWallet, walletSelectors } from './wallet'
import { receiveCryptocurrency } from './ticker'

// ------------------------------------
// Constants
// ------------------------------------
export const GET_INFO = 'GET_INFO'
export const RECEIVE_INFO = 'RECEIVE_INFO'
export const SET_HAS_SYNCED = 'SET_HAS_SYNCED'

const networkInfo = {
  bitcoin: {
    mainnet: {
      id: 'mainnet',
      name: 'Mainnet',
      explorerUrl: 'https://blockstream.info',
      bitcoinJsNetwork: networks.bitcoin.mainnet,
      unitPrefix: '',
    },
    testnet: {
      id: 'testnet',
      name: 'Testnet',
      explorerUrl: 'https://blockstream.info/testnet',
      bitcoinJsNetwork: networks.bitcoin.testnet,
      unitPrefix: 't',
    },
  },
  litecoin: {
    mainnet: {
      id: 'mainnet',
      name: 'Mainnet',
      explorerUrl: 'https://insight.litecore.io',
      bitcoinJsNetwork: networks.litecoin.mainnet,
      unitPrefix: '',
    },
    testnet: {
      id: 'testnet',
      name: 'Testnet',
      explorerUrl: 'https://testnet.litecore.io',
      bitcoinJsNetwork: networks.litecoin.testnet,
      unitPrefix: 't',
    },
  },
}

// ------------------------------------
// Actions
// ------------------------------------
export function getInfo() {
  return {
    type: GET_INFO,
  }
}

export const setHasSynced = hasSynced => async (dispatch, getState) => {
  dispatch({ type: SET_HAS_SYNCED, hasSynced })

  const state = getState()
  const pubKey = get(state, 'info.data.identity_pubkey')

  if (pubKey) {
    const updated = await window.db.nodes.update(pubKey, { hasSynced })
    if (updated === 0) {
      // The reason for a result of 0 can be either that the provided key was not found, or if the provided data was
      // identical to existing data so that nothing was updated. If we got a 0, try to add a new entry for the node.
      try {
        await window.db.nodes.add({ id: pubKey, hasSynced })
      } catch (e) {
        // Do nothing if there was an error - this indicates that the item already exists and was unchanged.
      }
    }
  }
}

// Send IPC event for getinfo
export const fetchInfo = () => async dispatch => {
  dispatch(getInfo())
  const grpc = await grpcService
  const info = await grpc.services.Lightning.getInfo()
  dispatch(receiveInfo(info))
}

// Receive IPC event for info
export const receiveInfo = data => async (dispatch, getState) => {
  // Save the node info.
  dispatch({ type: RECEIVE_INFO, data })

  const state = getState()

  dispatch(receiveCryptocurrency(data.chains[0].chain))

  // Now that we have the node info, load it's sync state.
  const node = await window.db.nodes.get({ id: data.identity_pubkey })
  if (node) {
    dispatch(setHasSynced(node.hasSynced))
  }

  // Now that we have the node info, get the current wallet addresses.
  dispatch(initAddresses())

  // Update the active wallet settings with info discovered from getinfo.
  const chain = get(state, 'info.chain')
  const network = get(state, 'info.network')

  const wallet = walletSelectors.activeWalletSettings(state)
  if (wallet && (wallet.chain !== chain || wallet.network !== network)) {
    wallet.chain = chain
    wallet.network = network
    await dispatch(putWallet(wallet))
  }
}

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [SET_HAS_SYNCED]: (state, { hasSynced }) => ({
    ...state,
    hasSynced,
  }),
  [GET_INFO]: state => ({ ...state, infoLoading: true }),
  [RECEIVE_INFO]: (state, { data }) => {
    const chain = get(data, 'chains[0].chain')
    const network = get(data, 'chains[0].network')
    return {
      ...state,
      infoLoading: false,
      infoLoaded: true,
      chain,
      network,
      data,
    }
  },
}

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  infoLoading: false,
  infoLoaded: false,
  hasSynced: undefined,
  chain: null,
  network: null,
  data: {},
  networks: networkInfo,
}

// Selectors
const infoSelectors = {}
infoSelectors.chainSelector = state => state.info.chain
infoSelectors.networkSelector = state => state.info.network
infoSelectors.networksSelector = state => state.info.networks
infoSelectors.infoLoading = state => state.info.infoLoading
infoSelectors.infoLoaded = state => state.info.infoLoaded
infoSelectors.hasSynced = state => state.info.hasSynced

infoSelectors.networkInfo = createSelector(
  infoSelectors.chainSelector,
  infoSelectors.networkSelector,
  infoSelectors.networksSelector,
  (chain, network, networks) => get(networks, `${chain}.${network}`)
)

export { infoSelectors }

export default function infoReducer(state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type]

  return handler ? handler(state, action) : state
}<commit_msg>refactor: add nodePub selector<commit_after>import { createSelector } from 'reselect'
import get from 'lodash.get'
import { networks } from '@zap/utils/crypto'
import { grpcService } from 'workers'
import { initAddresses } from './address'
import { putWallet, walletSelectors } from './wallet'
import { receiveCryptocurrency } from './ticker'

// ------------------------------------
// Constants
// ------------------------------------
export const GET_INFO = 'GET_INFO'
export const RECEIVE_INFO = 'RECEIVE_INFO'
export const SET_HAS_SYNCED = 'SET_HAS_SYNCED'

const networkInfo = {
  bitcoin: {
    mainnet: {
      id: 'mainnet',
      name: 'Mainnet',
      explorerUrl: 'https://blockstream.info',
      bitcoinJsNetwork: networks.bitcoin.mainnet,
      unitPrefix: '',
    },
    testnet: {
      id: 'testnet',
      name: 'Testnet',
      explorerUrl: 'https://blockstream.info/testnet',
      bitcoinJsNetwork: networks.bitcoin.testnet,
      unitPrefix: 't',
    },
  },
  litecoin: {
    mainnet: {
      id: 'mainnet',
      name: 'Mainnet',
      explorerUrl: 'https://insight.litecore.io',
      bitcoinJsNetwork: networks.litecoin.mainnet,
      unitPrefix: '',
    },
    testnet: {
      id: 'testnet',
      name: 'Testnet',
      explorerUrl: 'https://testnet.litecore.io',
      bitcoinJsNetwork: networks.litecoin.testnet,
      unitPrefix: 't',
    },
  },
}

// ------------------------------------
// Actions
// ------------------------------------
export function getInfo() {
  return {
    type: GET_INFO,
  }
}

export const setHasSynced = hasSynced => async (dispatch, getState) => {
  dispatch({ type: SET_HAS_SYNCED, hasSynced })

  const state = getState()
  const pubKey = get(state, 'info.data.identity_pubkey')

  if (pubKey) {
    const updated = await window.db.nodes.update(pubKey, { hasSynced })
    if (updated === 0) {
      // The reason for a result of 0 can be either that the provided key was not found, or if the provided data was
      // identical to existing data so that nothing was updated. If we got a 0, try to add a new entry for the node.
      try {
        await window.db.nodes.add({ id: pubKey, hasSynced })
      } catch (e) {
        // Do nothing if there was an error - this indicates that the item already exists and was unchanged.
      }
    }
  }
}

// Send IPC event for getinfo
export const fetchInfo = () => async dispatch => {
  dispatch(getInfo())
  const grpc = await grpcService
  const info = await grpc.services.Lightning.getInfo()
  dispatch(receiveInfo(info))
}

// Receive IPC event for info
export const receiveInfo = data => async (dispatch, getState) => {
  // Save the node info.
  dispatch({ type: RECEIVE_INFO, data })

  const state = getState()

  dispatch(receiveCryptocurrency(data.chains[0].chain))

  // Now that we have the node info, load it's sync state.
  const node = await window.db.nodes.get({ id: data.identity_pubkey })
  if (node) {
    dispatch(setHasSynced(node.hasSynced))
  }

  // Now that we have the node info, get the current wallet addresses.
  dispatch(initAddresses())

  // Update the active wallet settings with info discovered from getinfo.
  const chain = get(state, 'info.chain')
  const network = get(state, 'info.network')

  const wallet = walletSelectors.activeWalletSettings(state)
  if (wallet && (wallet.chain !== chain || wallet.network !== network)) {
    wallet.chain = chain
    wallet.network = network
    await dispatch(putWallet(wallet))
  }
}

// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
  [SET_HAS_SYNCED]: (state, { hasSynced }) => ({
    ...state,
    hasSynced,
  }),
  [GET_INFO]: state => ({ ...state, infoLoading: true }),
  [RECEIVE_INFO]: (state, { data }) => {
    const chain = get(data, 'chains[0].chain')
    const network = get(data, 'chains[0].network')
    return {
      ...state,
      infoLoading: false,
      infoLoaded: true,
      chain,
      network,
      data,
    }
  },
}

// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
  infoLoading: false,
  infoLoaded: false,
  hasSynced: undefined,
  chain: null,
  network: null,
  data: {},
  networks: networkInfo,
}

// Selectors
const infoSelectors = {}
infoSelectors.chainSelector = state => state.info.chain
infoSelectors.networkSelector = state => state.info.network
infoSelectors.networksSelector = state => state.info.networks
infoSelectors.infoLoading = state => state.info.infoLoading
infoSelectors.infoLoaded = state => state.info.infoLoaded
infoSelectors.hasSynced = state => state.info.hasSynced
infoSelectors.nodePub = state => {
  const parseFromDataUri = () => {
    const uri = get(state.info, 'data.uris[0]')
    return uri && uri.split('@')[0]
  }
  return get(state.info, 'data.identity_pubkey') || parseFromDataUri()
}

infoSelectors.networkInfo = createSelector(
  infoSelectors.chainSelector,
  infoSelectors.networkSelector,
  infoSelectors.networksSelector,
  (chain, network, networks) => get(networks, `${chain}.${network}`)
)

export { infoSelectors }

export default function infoReducer(state = initialState, action) {
  const handler = ACTION_HANDLERS[action.type]

  return handler ? handler(state, action) : state
}
{'fraction_non_alphanumeric': 0.176942404329339, 'fraction_numerical': 0.001352918438345574, 'mean_word_length': 2.6096965469131495, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7455006', 'n_tokens_mistral': 3145, 'n_tokens_neox': 3095, 'n_words': 820}