Browse Source

Merge pull request #21 from LN-Zap/feature/close-channel

Feature/close channel
renovate/lint-staged-8.x
jackmallers 7 years ago
committed by GitHub
parent
commit
393e2a1fc9
  1. 2
      app/components/CryptoIcon/CryptoIcon.js
  2. 601
      app/lnd/config/rpc.proto
  3. 20
      app/lnd/methods/closechannel.js
  4. 11
      app/lnd/methods/index.js
  5. 4
      app/lnd/methods/openchannel.js
  6. 16
      app/lnd/push/closechannel.js
  7. 2
      app/lnd/push/openchannel.js
  8. 61
      app/reducers/channels.js
  9. 26
      app/reducers/ipc.js
  10. 3
      app/routes/wallet/components/Wallet.js
  11. 10
      app/routes/wallet/components/components/Channels/Channels.js
  12. 12
      app/routes/wallet/components/components/Channels/components/ChannelModal/ChannelModal.js
  13. 4
      app/routes/wallet/containers/WalletContainer.js
  14. 6
      test/reducers/__snapshots__/channels.spec.js.snap

2
app/components/CryptoIcon/CryptoIcon.js

@ -17,7 +17,7 @@ const CryptoIcon = ({ currency, styles }) => {
CryptoIcon.propTypes = {
currency: PropTypes.string.isRequired,
styles: PropTypes.object.isRequired
styles: PropTypes.object
}
export default CryptoIcon

601
app/lnd/config/rpc.proto

File diff suppressed because it is too large

20
app/lnd/methods/closechannel.js

@ -0,0 +1,20 @@
import bitcore from 'bitcore-lib'
import pushclosechannel from '../push/closechannel'
const BufferUtil = bitcore.util.buffer
export default function closechannel(lnd, event, payload) {
const tx = payload.channel_point.funding_txid.match(/.{2}/g).reverse().join('')
const res = {
channel_point: {
funding_txid: BufferUtil.hexToBuffer(tx),
output_index: Number(payload.channel_point.output_index)
}
}
return new Promise((resolve, reject) =>
pushclosechannel(lnd, event, res)
.then(data => resolve(data))
.catch(error => reject(error))
)
}

11
app/lnd/methods/index.js

@ -2,6 +2,7 @@
import channelbalance from './channelbalance'
import channels from './channels'
import closechannel from './closechannel'
import connectpeer from './connectpeer'
import createinvoice from './createinvoice'
import disconnectpeer from './disconnectpeer'
@ -100,6 +101,16 @@ export default function (lnd, event, msg, data) {
})
.catch(error => console.log('openChannel error: ', error))
break
case 'closeChannel':
// Response is empty. Streaming updates on channel status and updates
// { channel_point, force } = data
closechannel(lnd, event, data)
.then((result) => {
console.log('CLOSE CHANNEL: ', result)
event.sender.send('closeChannelSuccessful')
})
.catch(error => console.log('closeChannel error: ', error))
break
case 'connectPeer':
// Returns a peer_id. Pass the pubkey, host and peer_id so we can add a new peer to the list
// { pubkey, host } = data

4
app/lnd/methods/openchannel.js

@ -1,5 +1,5 @@
import bitcore from 'bitcore-lib'
import pushchannel from '../push/channel'
import pushopenchannel from '../push/openchannel'
const BufferUtil = bitcore.util.buffer
@ -12,7 +12,7 @@ export default function openchannel(lnd, event, payload) {
}
return new Promise((resolve, reject) =>
pushchannel(lnd, event, res)
pushopenchannel(lnd, event, res)
.then(data => resolve(data))
.catch(error => reject(error))
)

16
app/lnd/push/closechannel.js

@ -0,0 +1,16 @@
export default function pushclosechannel(lnd, event, payload) {
return new Promise((resolve, reject) => {
try {
const call = lnd.closeChannel(payload)
call.on('data', data => event.sender.send('pushclosechannelupdated', { data }))
call.on('end', () => event.sender.send('pushclosechannelend'))
call.on('error', error => event.sender.send('pushclosechannelerror', { error }))
call.on('status', status => event.sender.send('pushclosechannelstatus', { status }))
resolve(null, payload)
} catch (error) {
reject(error, null)
}
})
}

2
app/lnd/push/channel.js → app/lnd/push/openchannel.js

@ -1,4 +1,4 @@
export default function pushchannel(lnd, event, payload) {
export default function pushopenchannel(lnd, event, payload) {
return new Promise((resolve, reject) => {
try {
const call = lnd.openChannel(payload)

61
app/reducers/channels.js

@ -14,6 +14,10 @@ export const OPENING_CHANNEL = 'OPENING_CHANNEL'
export const OPENING_SUCCESSFUL = 'OPENING_SUCCESSFUL'
export const OPENING_FAILURE = 'OPENING_FAILURE'
export const CLOSING_CHANNEL = 'CLOSING_CHANNEL'
export const CLOSING_SUCCESSFUL = 'CLOSING_SUCCESSFUL'
export const CLOSING_FAILURE = 'CLOSING_FAILURE'
// ------------------------------------
// Actions
// ------------------------------------
@ -44,6 +48,12 @@ export function openingChannel() {
}
}
export function closingChannel() {
return {
type: CLOSING_CHANNEL
}
}
export function openingSuccessful() {
return {
type: OPENING_SUCCESSFUL
@ -97,6 +107,51 @@ export const pushchannelstatus = () => (dispatch) => {
dispatch(fetchChannels())
}
// Send IPC event for opening a channel
export const closeChannel = ({ channel_point }) => (dispatch) => {
dispatch(closingChannel())
const channelPoint = channel_point.split(':')
ipcRenderer.send(
'lnd',
{
msg: 'closeChannel',
data: {
channel_point: {
funding_txid: channelPoint[0],
output_index: channelPoint[1]
},
force: true
}
}
)
}
// TODO: Decide how to handle streamed updates for closing channels
// Receive IPC event for closeChannel
export const closeChannelSuccessful = () => (dispatch) => {
dispatch(fetchChannels())
}
// Receive IPC event for updated closing channel
export const pushclosechannelupdated = () => (dispatch) => {
dispatch(fetchChannels())
}
// Receive IPC event for closing channel end
export const pushclosechannelend = () => (dispatch) => {
dispatch(fetchChannels())
}
// Receive IPC event for closing channel error
export const pushclosechannelerror = () => (dispatch) => {
dispatch(fetchChannels())
}
// Receive IPC event for closing channel status
export const pushclosechannelstatus = () => (dispatch) => {
dispatch(fetchChannels())
}
// ------------------------------------
// Action Handlers
// ------------------------------------
@ -112,7 +167,8 @@ const ACTION_HANDLERS = {
{ ...state, channelsLoading: false, channels, pendingChannels }
),
[OPENING_CHANNEL]: state => ({ ...state, openingChannel: true })
[OPENING_CHANNEL]: state => ({ ...state, openingChannel: true }),
[CLOSING_CHANNEL]: state => ({ ...state, closingChannel: true })
}
const channelsSelectors = {}
@ -158,7 +214,8 @@ const initialState = {
local_amt: '',
push_amt: ''
},
openingChannel: false
openingChannel: false,
closingChannel: false
}
export default function channelsReducer(state = initialState, action) {

26
app/reducers/ipc.js

@ -5,11 +5,19 @@ import { receiveCryptocurrency } from './ticker'
import { receivePeers, connectSuccess, disconnectSuccess } from './peers'
import {
receiveChannels,
channelSuccessful,
pushchannelupdated,
pushchannelend,
pushchannelerror,
pushchannelstatus
pushchannelstatus,
closeChannelSuccessful,
pushclosechannelupdated,
pushclosechannelend,
pushclosechannelerror,
pushclosechannelstatus
} from './channels'
import { receivePayments, paymentSuccessful } from './payment'
import { receiveInvoices, createdInvoice, receiveFormInvoice } from './invoice'
@ -18,21 +26,35 @@ import { receiveBalance } from './balance'
// Import all receiving IPC event handlers and pass them into createIpc
const ipc = createIpc({
receiveInfo,
receivePeers,
receiveChannels,
receivePayments,
receiveInvoices,
receiveInvoice: receiveFormInvoice,
receiveBalance,
createdInvoice,
receiveBalance,
paymentSuccessful,
channelSuccessful,
pushchannelupdated,
pushchannelend,
pushchannelerror,
pushchannelstatus,
closeChannelSuccessful,
pushclosechannelupdated,
pushclosechannelend,
pushclosechannelerror,
pushclosechannelstatus,
connectSuccess,
disconnectSuccess,
receiveAddress,
receiveCryptocurrency
})

3
app/routes/wallet/components/Wallet.js

@ -31,6 +31,7 @@ class Wallet extends Component {
disconnectRequest,
allChannels,
openChannel,
closeChannel,
currentTicker,
explorerLinkBase
} = this.props
@ -75,6 +76,7 @@ class Wallet extends Component {
channelForm={channelForm}
setChannelForm={setChannelForm}
openChannel={openChannel}
closeChannel={closeChannel}
currentTicker={currentTicker}
explorerLinkBase={explorerLinkBase}
/>
@ -101,6 +103,7 @@ Wallet.propTypes = {
disconnectRequest: PropTypes.func.isRequired,
allChannels: PropTypes.array.isRequired,
openChannel: PropTypes.func.isRequired,
closeChannel: PropTypes.func.isRequired,
newAddress: PropTypes.func.isRequired,
address: PropTypes.object.isRequired,
currentTicker: PropTypes.object.isRequired,

10
app/routes/wallet/components/components/Channels/Channels.js

@ -19,11 +19,18 @@ const Channels = ({
setChannelForm,
allChannels,
openChannel,
closeChannel,
currentTicker,
explorerLinkBase
}) => (
<div className={styles.channels}>
<ChannelModal isOpen={channelModalOpen} resetChannel={setChannel} channel={modalChannel} explorerLinkBase={explorerLinkBase} />
<ChannelModal
isOpen={channelModalOpen}
resetChannel={setChannel}
channel={modalChannel}
explorerLinkBase={explorerLinkBase}
closeChannel={closeChannel}
/>
<ChannelForm form={channelForm} setForm={setChannelForm} ticker={ticker} peers={peers} openChannel={openChannel} currentTicker={currentTicker} />
<div className={styles.header}>
<h3>Channels</h3>
@ -88,6 +95,7 @@ Channels.propTypes = {
setChannelForm: PropTypes.func.isRequired,
allChannels: PropTypes.array.isRequired,
openChannel: PropTypes.func.isRequired,
closeChannel: PropTypes.func.isRequired,
currentTicker: PropTypes.object.isRequired,
explorerLinkBase: PropTypes.string.isRequired
}

12
app/routes/wallet/components/components/Channels/components/ChannelModal/ChannelModal.js

@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import ReactModal from 'react-modal'
import styles from './ChannelModal.scss'
const ChannelModal = ({ isOpen, resetChannel, channel, explorerLinkBase }) => {
const ChannelModal = ({ isOpen, resetChannel, channel, explorerLinkBase, closeChannel }) => {
const customStyles = {
overlay: {
cursor: 'pointer',
@ -21,6 +21,11 @@ const ChannelModal = ({ isOpen, resetChannel, channel, explorerLinkBase }) => {
}
}
const closeChannelClicked = () => {
closeChannel({ channel_point: channel.channel_point })
resetChannel(null)
}
return (
<ReactModal
isOpen={isOpen}
@ -71,7 +76,7 @@ const ChannelModal = ({ isOpen, resetChannel, channel, explorerLinkBase }) => {
<dd>{channel.num_updates}</dd>
</dl>
</div>
<div className={styles.close}>
<div className={styles.close} onClick={closeChannelClicked}>
<div>Close channel</div>
</div>
<footer className={styles.active}>
@ -89,7 +94,8 @@ ChannelModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
resetChannel: PropTypes.func.isRequired,
channel: PropTypes.object,
explorerLinkBase: PropTypes.string.isRequired
explorerLinkBase: PropTypes.string.isRequired,
closeChannel: PropTypes.func.isRequired
}
export default ChannelModal

4
app/routes/wallet/containers/WalletContainer.js

@ -16,7 +16,8 @@ import {
setChannel,
channelsSelectors,
setChannelForm,
openChannel
openChannel,
closeChannel
} from '../../../reducers/channels'
import Wallet from '../components/Wallet'
@ -32,6 +33,7 @@ const mapDispatchToProps = {
fetchPendingChannels,
setChannel,
openChannel,
closeChannel,
setPeerForm,
setChannelForm

6
test/reducers/__snapshots__/channels.spec.js.snap

@ -11,6 +11,7 @@ Object {
},
"channels": Array [],
"channelsLoading": true,
"closingChannel": false,
"openingChannel": false,
"pendingChannels": Object {
"pending_closing_channels": Array [],
@ -32,6 +33,7 @@ Object {
},
"channels": Array [],
"channelsLoading": false,
"closingChannel": false,
"openingChannel": true,
"pendingChannels": Object {
"pending_closing_channels": Array [],
@ -56,6 +58,7 @@ Object {
2,
],
"channelsLoading": false,
"closingChannel": false,
"openingChannel": false,
"pendingChannels": Array [
3,
@ -75,6 +78,7 @@ Object {
},
"channels": Array [],
"channelsLoading": false,
"closingChannel": false,
"openingChannel": false,
"pendingChannels": Object {
"pending_closing_channels": Array [],
@ -96,6 +100,7 @@ Object {
},
"channels": Array [],
"channelsLoading": false,
"closingChannel": false,
"openingChannel": false,
"pendingChannels": Object {
"pending_closing_channels": Array [],
@ -117,6 +122,7 @@ Object {
},
"channels": Array [],
"channelsLoading": false,
"closingChannel": false,
"openingChannel": false,
"pendingChannels": Object {
"pending_closing_channels": Array [],

Loading…
Cancel
Save