You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

317 lines
8.0 KiB

import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron'
import { bech32 } from 'lib/utils'
// ------------------------------------
// Constants
// ------------------------------------
export const GET_DESCRIBE_NETWORK = 'GET_DESCRIBE_NETWORK'
export const RECEIVE_DESCRIBE_NETWORK = 'RECEIVE_DESCRIBE_NETWORK'
export const GET_QUERY_ROUTES = 'GET_QUERY_ROUTES'
export const RECEIVE_QUERY_ROUTES = 'RECEIVE_QUERY_ROUTES'
export const SET_CURRENT_ROUTE = 'SET_CURRENT_ROUTE'
export const SET_CURRENT_CHANNEL = 'SET_CURRENT_CHANNEL'
export const SET_CURRENT_TAB = 'SET_CURRENT_TAB'
export const SET_CURRENT_PEER = 'SET_CURRENT_PEER'
export const UPDATE_PAY_REQ = 'UPDATE_PAY_REQ'
export const RESET_PAY_REQ = 'RESET_PAY_REQ'
export const UPDATE_SELECTED_PEERS = 'UPDATE_SELECTED_PEERS'
export const CLEAR_SELECTED_PEERS = 'CLEAR_SELECTED_PEERS'
export const UPDATE_SELECTED_CHANNELS = 'UPDATE_SELECTED_CHANNELS'
export const CLEAR_SELECTED_CHANNELS = 'CLEAR_SELECTED_CHANNELS'
export const GET_INFO_AND_QUERY_ROUTES = 'GET_INFO_AND_QUERY_ROUTES'
export const RECEIVE_INFO_AND_QUERY_ROUTES = 'RECEIVE_INFO_AND_QUERY_ROUTES'
export const CLEAR_QUERY_ROUTES = 'CLEAR_QUERY_ROUTES'
// ------------------------------------
// Actions
// ------------------------------------
export function getDescribeNetwork() {
return {
type: GET_DESCRIBE_NETWORK
}
}
export function getQueryRoutes(pubkey) {
return {
type: GET_QUERY_ROUTES,
pubkey
}
}
export function setCurrentRoute(route) {
return {
type: SET_CURRENT_ROUTE,
route
}
}
export function setCurrentChannel(selectedChannel) {
return {
type: SET_CURRENT_CHANNEL,
selectedChannel
}
}
export function setCurrentTab(currentTab) {
return {
type: SET_CURRENT_TAB,
currentTab
}
}
export function setCurrentPeer(currentPeer) {
return {
type: SET_CURRENT_PEER,
currentPeer
}
}
export function updatePayReq(pay_req) {
return {
type: UPDATE_PAY_REQ,
pay_req
}
}
export function resetPayReq() {
return {
type: RESET_PAY_REQ
}
}
export function updateSelectedPeers(peer) {
return {
type: UPDATE_SELECTED_PEERS,
peer
}
}
export function updateSelectedChannels(channel) {
return {
type: UPDATE_SELECTED_CHANNELS,
channel
}
}
export function getInvoiceAndQueryRoutes() {
return {
type: GET_INFO_AND_QUERY_ROUTES
}
}
export function clearQueryRoutes() {
return {
type: CLEAR_QUERY_ROUTES
}
}
export function clearSelectedPeers() {
return {
type: CLEAR_SELECTED_PEERS
}
}
export function clearSelectedChannels() {
return {
type: CLEAR_SELECTED_CHANNELS
}
}
// Send IPC event for describeNetwork
export const fetchDescribeNetwork = () => dispatch => {
dispatch(getDescribeNetwork())
ipcRenderer.send('lnd', { msg: 'describeNetwork' })
}
// Receive IPC event for describeNetwork
export const receiveDescribeNetwork = (event, { nodes, edges }) => dispatch =>
dispatch({ type: RECEIVE_DESCRIBE_NETWORK, nodes, edges })
export const queryRoutes = (pubkey, amount) => dispatch => {
dispatch(getQueryRoutes(pubkey))
ipcRenderer.send('lnd', { msg: 'queryRoutes', data: { pubkey, amount } })
}
export const receiveQueryRoutes = (event, { routes }) => dispatch =>
dispatch({ type: RECEIVE_QUERY_ROUTES, routes })
// take a payreq and query routes for it
export const fetchInvoiceAndQueryRoutes = payreq => dispatch => {
dispatch(getInvoiceAndQueryRoutes())
ipcRenderer.send('lnd', { msg: 'getInvoiceAndQueryRoutes', data: { payreq } })
}
export const receiveInvoiceAndQueryRoutes = (event, { routes }) => dispatch =>
dispatch({ type: RECEIVE_INFO_AND_QUERY_ROUTES, routes })
// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
[GET_DESCRIBE_NETWORK]: state => ({ ...state, networkLoading: true }),
[RECEIVE_DESCRIBE_NETWORK]: (state, { nodes, edges }) => ({
...state,
networkLoading: false,
nodes,
edges
}),
[GET_QUERY_ROUTES]: (state, { pubkey }) => ({
...state,
networkLoading: true,
selectedNode: { pubkey, routes: [], currentRoute: {} }
}),
[RECEIVE_QUERY_ROUTES]: (state, { routes }) => ({
...state,
networkLoading: false,
selectedNode: { pubkey: state.selectedNode.pubkey, routes, currentRoute: routes[0] }
}),
[SET_CURRENT_ROUTE]: (state, { route }) => ({ ...state, currentRoute: route }),
[SET_CURRENT_CHANNEL]: (state, { selectedChannel }) => ({ ...state, selectedChannel }),
[SET_CURRENT_TAB]: (state, { currentTab }) => ({ ...state, currentTab }),
[SET_CURRENT_PEER]: (state, { currentPeer }) => ({ ...state, currentPeer }),
[UPDATE_PAY_REQ]: (state, { pay_req }) => ({ ...state, pay_req }),
[RESET_PAY_REQ]: state => ({ ...state, pay_req: '' }),
[GET_INFO_AND_QUERY_ROUTES]: state => ({ ...state, fetchingInvoiceAndQueryingRoutes: true }),
[RECEIVE_INFO_AND_QUERY_ROUTES]: (state, { routes }) => ({
...state,
fetchingInvoiceAndQueryingRoutes: false,
payReqRoutes: routes
}),
[CLEAR_QUERY_ROUTES]: state => ({ ...state, payReqRoutes: [], currentRoute: {} }),
[UPDATE_SELECTED_PEERS]: (state, { peer }) => {
let selectedPeers
if (state.selectedPeers.includes(peer)) {
selectedPeers = state.selectedPeers.filter(
selectedPeer => selectedPeer.pub_key !== peer.pub_key
)
}
if (!state.selectedPeers.includes(peer)) {
selectedPeers = [...state.selectedPeers, peer]
}
return {
...state,
selectedPeers
}
},
[CLEAR_SELECTED_PEERS]: state => ({ ...state, selectedPeers: [] }),
[UPDATE_SELECTED_CHANNELS]: (state, { channel }) => {
let selectedChannels
if (state.selectedChannels.includes(channel)) {
selectedChannels = state.selectedChannels.filter(
selectedChannel => selectedChannel.chan_id !== channel.chan_id
)
}
if (!state.selectedChannels.includes(channel)) {
selectedChannels = [...state.selectedChannels, channel]
}
return {
...state,
selectedChannels
}
},
[CLEAR_SELECTED_CHANNELS]: state => ({ ...state, selectedChannels: [] })
}
// ------------------------------------
// Selectors
// ------------------------------------
const networkSelectors = {}
const selectedPeersSelector = state => state.network.selectedPeers
const selectedChannelsSelector = state => state.network.selectedChannels
const payReqSelector = state => state.network.pay_req
const currentRouteSelector = state => state.network.currentRoute
// networkSelectors.currentRouteHopChanIds = createSelector(
// currentRouteSelector,
// (currentRoute) => {
// if (!currentRoute.hops) { return [] }
// return currentRoute.hops.map(hop => hop.chan_id)
// }
// )
networkSelectors.selectedPeerPubkeys = createSelector(selectedPeersSelector, peers =>
peers.map(peer => peer.pub_key)
)
networkSelectors.selectedChannelIds = createSelector(selectedChannelsSelector, channels =>
channels.map(channel => channel.chan_id)
)
networkSelectors.payReqIsLn = createSelector(payReqSelector, input => {
if (!input.startsWith('ln')) {
return false
}
try {
bech32.decode(input)
return true
} catch (e) {
return false
}
})
networkSelectors.currentRouteChanIds = createSelector(currentRouteSelector, route => {
if (!route.hops || !route.hops.length) {
return []
}
return route.hops.map(hop => hop.chan_id)
})
export { networkSelectors }
// ------------------------------------
// Initial State
// ------------------------------------
const initialState = {
networkLoading: false,
nodes: [],
edges: [],
selectedChannel: {},
currentTab: 1,
currentPeer: {},
currentRoute: {},
fetchingInvoiceAndQueryingRoutes: false,
pay_req: '',
payReqRoutes: [],
selectedPeers: [],
selectedChannels: []
}
// ------------------------------------
// Reducer
// ------------------------------------
export default function activityReducer(state = initialState, action) {
const handler = ACTION_HANDLERS[action.type]
return handler ? handler(state, action) : state
}