Browse Source

feature(lnd-ipa): refactor out nodejs completely

renovate/lint-staged-8.x
Jack Mallers 8 years ago
parent
commit
2553622cbc
  1. 10
      app/lnd/methods/connectpeer.js
  2. 10
      app/lnd/methods/disconnectpeer.js
  3. 41
      app/lnd/methods/index.js
  4. 18
      app/lnd/methods/openchannel.js
  5. 16
      app/lnd/push/channel.js
  6. 1
      app/reducers/balance.js
  7. 37
      app/reducers/channels.js
  8. 20
      app/reducers/ipc.js
  9. 13
      app/reducers/payment.js
  10. 49
      app/reducers/peers.js
  11. 3
      app/routes/app/components/App.js
  12. 20
      app/routes/app/components/components/Socket.js
  13. 6
      app/routes/wallet/components/components/Channels/components/ChannelForm/ChannelForm.js
  14. 5
      app/routes/wallet/components/components/Peers/components/PeerForm/PeerForm.js
  15. 7
      app/routes/wallet/components/components/Peers/components/PeerModal/PeerModal.js
  16. 1
      package.json
  17. 42
      yarn.lock

10
app/lnd/methods/connectpeer.js

@ -0,0 +1,10 @@
// LND Connect to a peer
export default function connectpeer(lnd, { pubkey, host }) {
return new Promise((resolve, reject) => {
lnd.connectPeer({ addr: { pubkey, host }, perm: true }, (err, data) => {
if (err) { reject(err) }
resolve(data)
})
})
}

10
app/lnd/methods/disconnectpeer.js

@ -0,0 +1,10 @@
// LND Disconnect from a peer
export default function disconnectpeer(lnd, { pubkey }) {
return new Promise((resolve, reject) => {
lnd.disconnectPeer({ pub_key: pubkey }, (err, data) => {
if (err) { reject(err) }
resolve(data)
})
})
}

41
app/lnd/methods/index.js

@ -1,10 +1,13 @@
import allchannels from './allchannels' import allchannels from './allchannels'
import channelbalance from './channelbalance' import channelbalance from './channelbalance'
import channels from './channels' import channels from './channels'
import connectpeer from './connectpeer'
import createinvoice from './createinvoice' import createinvoice from './createinvoice'
import disconnectpeer from './disconnectpeer'
import info from './info' import info from './info'
import invoice from './invoice' import invoice from './invoice'
import invoices from './invoices' import invoices from './invoices'
import openchannel from './openchannel'
import payinvoice from './payinvoice' import payinvoice from './payinvoice'
import payments from './payments' import payments from './payments'
import peers from './peers' import peers from './peers'
@ -56,18 +59,48 @@ export default function(lnd, event, msg, data) {
break break
case 'createInvoice': case 'createInvoice':
// Invoice looks like { r_hash: Buffer, payment_request: '' } // Invoice looks like { r_hash: Buffer, payment_request: '' }
const { memo, value } = data // { memo, value } = data
createInvoice(lnd, { memo, value }) createInvoice(lnd, data)
.then(invoice => event.sender.send('createdInvoice', Object.assign(invoice, { memo, value, r_hash: new Buffer(invoice.r_hash,'hex').toString('hex') }))) .then(invoice => event.sender.send('createdInvoice', Object.assign(invoice, { memo, value, r_hash: new Buffer(invoice.r_hash,'hex').toString('hex') })))
.catch(error => console.log('createInvoice error: ', error)) .catch(error => console.log('createInvoice error: ', error))
break break
case 'sendPayment': case 'sendPayment':
// Payment looks like { payment_preimage: Buffer, payment_route: Object } // Payment looks like { payment_preimage: Buffer, payment_route: Object }
const { paymentRequest } = data // { paymentRequest } = data
sendPayment(lnd, { paymentRequest }) sendPayment(lnd, data)
.then(payment => event.sender.send('paymentSuccessful')) .then(payment => event.sender.send('paymentSuccessful'))
.catch(error => console.log('sendPayment error: ', error)) .catch(error => console.log('sendPayment error: ', error))
break break
case 'openChannel':
// Response is empty. Streaming updates on channel status and updates
// { pubkey, localamt, pushamt } = data
openchannel(lnd, event, data)
.then(channel => {
console.log('CHANNEL: ', channel)
event.sender.send('channelSuccessful', { channel })
})
.catch(error => console.log('openChannel 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
connectpeer(lnd, data)
.then(({ peer_id }) => {
console.log('peer_id: ', peer_id)
event.sender.send('connectSuccess', { pub_key: data.pubkey, address: data.host, peer_id })
})
.catch(error => console.log('connectPeer error: ', error))
break
case 'disconnectPeer':
// Empty response. Pass back pubkey on success to remove it from the peers list
// { pubkey } = data
disconnectpeer(lnd, data)
.then(() => {
console.log('pubkey: ', data.pubkey)
event.sender.send('disconnectSuccess', { pubkey: data.pubkey })
})
.catch(error => console.log('disconnectPeer error: ', error))
break
default: default:
return return
} }

18
app/lnd/methods/openchannel.js

@ -0,0 +1,18 @@
import pushchannel from '../push/channel'
import bitcore from 'bitcore-lib'
const BufferUtil = bitcore.util.buffer
export default function openchannel(lnd, event, data) {
const { pubkey, localamt, pushamt } = data
const payload = {
node_pubkey: BufferUtil.hexToBuffer(pubkey),
local_funding_amount: Number(localamt),
push_sat: Number(pushamt)
}
return new Promise((resolve, reject) =>
pushchannel(lnd, event, payload)
.then(data => resolve(data))
.catch(error => reject(err))
)
}

16
app/lnd/push/channel.js

@ -0,0 +1,16 @@
export default function pushchannel(lnd, event, payload) {
return new Promise((resolve, reject) => {
try {
const call = lnd.openChannel(payload)
call.on('data', data => event.sender.send('pushchannelupdated', { data }))
call.on('end', () => event.sender.send('pushchannelend'))
call.on('error', error => event.sender.send('pushchannelerror', { error }))
call.on('status', status => event.sender.send('pushchannelstatus', { status }))
resolve(null, payload)
} catch (error) {
reject(error, null)
}
})
}

1
app/reducers/balance.js

@ -1,5 +1,4 @@
import { ipcRenderer } from 'electron' import { ipcRenderer } from 'electron'
import { callApis } from '../api'
// ------------------------------------ // ------------------------------------
// Constants // Constants
// ------------------------------------ // ------------------------------------

37
app/reducers/channels.js

@ -1,6 +1,5 @@
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron' import { ipcRenderer } from 'electron'
import { callApi, callApis } from '../api'
// ------------------------------------ // ------------------------------------
// Constants // Constants
// ------------------------------------ // ------------------------------------
@ -66,18 +65,36 @@ export const fetchChannels = () => async (dispatch) => {
// Receive IPC event for channels // Receive IPC event for channels
export const receiveChannels = (event, { channels, pendingChannels }) => dispatch => dispatch({ type: RECEIVE_CHANNELS, channels, pendingChannels }) export const receiveChannels = (event, { channels, pendingChannels }) => dispatch => dispatch({ type: RECEIVE_CHANNELS, channels, pendingChannels })
export const openChannel = ({ pubkey, localamt, pushamt }) => async (dispatch) => { // Send IPC event for opening a channel
const payload = { pubkey, localamt, pushamt } export const openChannel = ({ pubkey, localamt, pushamt }) => dispatch => {
dispatch(openingChannel()) dispatch(openingChannel())
const channel = await callApi('addchannel', 'post', payload) ipcRenderer.send('lnd', { msg: 'openChannel', data: { pubkey, localamt, pushamt } })
}
if (channel.data) { // TODO: Decide how to handle streamed updates for channels
dispatch(openingSuccessful()) // Receive IPC event for openChannel
} else { export const channelSuccessful = (event, { channel }) => dispatch => {
dispatch(openingFailure()) dispatch(fetchChannels())
} }
// Receive IPC event for updated channel
export const pushchannelupdated = (event, data) => dispatch => {
dispatch(fetchChannels())
}
// Receive IPC event for channel end
export const pushchannelend = (event, data) => dispatch => {
dispatch(fetchChannels())
}
// Receive IPC event for channel error
export const pushchannelerror = (event, data) => dispatch => {
dispatch(fetchChannels())
}
return channel // Receive IPC event for channel status
export const pushchannelstatus = (event, data) => dispatch => {
dispatch(fetchChannels())
} }
// ------------------------------------ // ------------------------------------

20
app/reducers/ipc.js

@ -1,7 +1,14 @@
import createIpc from 'redux-electron-ipc' import createIpc from 'redux-electron-ipc'
import { receiveInfo } from './info' import { receiveInfo } from './info'
import { receivePeers } from './peers' import { receivePeers, connectSuccess, disconnectSuccess } from './peers'
import { receiveChannels } from './channels' import {
receiveChannels,
channelSuccessful,
pushchannelupdated,
pushchannelend,
pushchannelerror,
pushchannelstatus
} from './channels'
import { receivePayments, paymentSuccessful } from './payment' import { receivePayments, paymentSuccessful } from './payment'
import { receiveInvoices, createdInvoice, receiveFormInvoice } from './invoice' import { receiveInvoices, createdInvoice, receiveFormInvoice } from './invoice'
import { receiveBalance } from './balance' import { receiveBalance } from './balance'
@ -16,7 +23,14 @@ const ipc = createIpc({
'receiveInvoice': receiveFormInvoice, 'receiveInvoice': receiveFormInvoice,
'receiveBalance': receiveBalance, 'receiveBalance': receiveBalance,
'createdInvoice': createdInvoice, 'createdInvoice': createdInvoice,
'paymentSuccessful': paymentSuccessful 'paymentSuccessful': paymentSuccessful,
'channelSuccessful': channelSuccessful,
'pushchannelupdated': pushchannelupdated,
'pushchannelend': pushchannelend,
'pushchannelerror': pushchannelerror,
'pushchannelstatus': pushchannelstatus,
'connectSuccess': connectSuccess,
'disconnectSuccess': disconnectSuccess
}) })
export default ipc export default ipc

13
app/reducers/payment.js

@ -58,19 +58,6 @@ export const fetchPayments = () => dispatch => {
// Receive IPC event for payments // Receive IPC event for payments
export const receivePayments = (event, { payments }) => dispatch => dispatch({ type: RECEIVE_PAYMENTS, payments }) export const receivePayments = (event, { payments }) => dispatch => dispatch({ type: RECEIVE_PAYMENTS, payments })
// export const payInvoice = payment_request => async (dispatch) => {
// dispatch(sendPayment())
// const payment = await callApi('sendpayment', 'post', { payment_request })
// if (payment) {
// dispatch(fetchPayments())
// } else {
// dispatch(paymentFailed())
// }
// return payment
// }
export const payInvoice = paymentRequest => dispatch => { export const payInvoice = paymentRequest => dispatch => {
dispatch(sendPayment()) dispatch(sendPayment())
ipcRenderer.send('lnd', { msg: 'sendPayment', data: { paymentRequest } }) ipcRenderer.send('lnd', { msg: 'sendPayment', data: { paymentRequest } })

49
app/reducers/peers.js

@ -1,6 +1,5 @@
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
import { ipcRenderer } from 'electron' import { ipcRenderer } from 'electron'
import { callApi } from '../api'
// ------------------------------------ // ------------------------------------
// Constants // Constants
// ------------------------------------ // ------------------------------------
@ -28,13 +27,6 @@ export function connectPeer() {
} }
} }
export function connectSuccess(peer) {
return {
type: CONNECT_SUCCESS,
peer
}
}
export function connectFailure() { export function connectFailure() {
return { return {
type: CONNECT_FAILURE type: CONNECT_FAILURE
@ -47,13 +39,6 @@ export function disconnectPeer() {
} }
} }
export function disconnectSuccess(pubkey) {
return {
type: DISCONNECT_SUCCESS,
pubkey
}
}
export function disconnectFailure() { export function disconnectFailure() {
return { return {
type: DISCONNECT_FAILURE type: DISCONNECT_FAILURE
@ -89,40 +74,34 @@ export const fetchPeers = () => async (dispatch) => {
// Receive IPC event for peers // Receive IPC event for peers
export const receivePeers = (event, { peers }) => dispatch => dispatch({ type: RECEIVE_PEERS, peers }) export const receivePeers = (event, { peers }) => dispatch => dispatch({ type: RECEIVE_PEERS, peers })
export const connectRequest = ({ pubkey, host }) => async (dispatch) => { // Send IPC event for connecting to a peer
export const connectRequest = ({ pubkey, host }) => dispatch => {
dispatch(connectPeer()) dispatch(connectPeer())
const success = await callApi('connect', 'post', { pubkey, host }) ipcRenderer.send('lnd', { msg: 'connectPeer', data: { pubkey, host } })
if (success.data) {
dispatch(connectSuccess({ pub_key: pubkey, address: host, peer_id: success.data.peer_id }))
} else {
dispatch(connectFailure())
}
return success
} }
export const disconnectRequest = ({ pubkey }) => async (dispatch) => { // Send IPC receive for successfully connecting to a peer
dispatch(disconnectPeer()) export const connectSuccess = (event, peer) => dispatch => dispatch({ type: CONNECT_SUCCESS, peer })
const success = await callApi('disconnect', 'post', { pubkey })
if (success) {
dispatch(disconnectSuccess(pubkey))
} else {
dispatch(disconnectFailure())
}
return success // Send IPC send for disconnecting from a peer
export const disconnectRequest = ({ pubkey }) => dispatch => {
dispatch(disconnectPeer())
ipcRenderer.send('lnd', { msg: 'disconnectPeer', data: { pubkey } })
} }
// Send IPC receive for successfully disconnecting from a peer
export const disconnectSuccess = (event, { pubkey }) => dispatch => dispatch({ type: DISCONNECT_SUCCESS, pubkey })
// ------------------------------------ // ------------------------------------
// Action Handlers // Action Handlers
// ------------------------------------ // ------------------------------------
const ACTION_HANDLERS = { const ACTION_HANDLERS = {
[DISCONNECT_PEER]: state => ({ ...state, disconnecting: true }), [DISCONNECT_PEER]: state => ({ ...state, disconnecting: true }),
[DISCONNECT_SUCCESS]: (state, { pubkey }) => ({ ...state, disconnecting: false, peers: state.peers.filter(peer => peer.pub_key !== pubkey) }), [DISCONNECT_SUCCESS]: (state, { pubkey }) => ({ ...state, disconnecting: false, peer: null, peers: state.peers.filter(peer => peer.pub_key !== pubkey) }),
[DISCONNECT_FAILURE]: state => ({ ...state, disconnecting: false }), [DISCONNECT_FAILURE]: state => ({ ...state, disconnecting: false }),
[CONNECT_PEER]: state => ({ ...state, connecting: true }), [CONNECT_PEER]: state => ({ ...state, connecting: true }),
[CONNECT_SUCCESS]: (state, { peer }) => ({ ...state, connecting: false, peers: [...state.peers, peer] }), [CONNECT_SUCCESS]: (state, { peer }) => ({ ...state, connecting: false, peerForm: { pubkey: '', host: '', isOpen: false }, peers: [...state.peers, peer] }),
[CONNECT_FAILURE]: state => ({ ...state, connecting: false }), [CONNECT_FAILURE]: state => ({ ...state, connecting: false }),
[SET_PEER_FORM]: (state, { form }) => ({ ...state, peerForm: Object.assign({}, state.peerForm, form) }), [SET_PEER_FORM]: (state, { form }) => ({ ...state, peerForm: Object.assign({}, state.peerForm, form) }),

3
app/routes/app/components/App.js

@ -3,7 +3,6 @@ import React, { Component } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import Form from './components/Form' import Form from './components/Form'
import Nav from './components/Nav' import Nav from './components/Nav'
import Socket from './components/Socket'
import styles from './App.scss' import styles from './App.scss'
class App extends Component { class App extends Component {
@ -62,8 +61,6 @@ class App extends Component {
<div className={styles.content}> <div className={styles.content}>
{children} {children}
</div> </div>
<Socket fetchChannels={fetchChannels} />
</div> </div>
) )
} }

20
app/routes/app/components/components/Socket.js

@ -1,20 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import Websocket from 'react-websocket'
const Socket = ({ fetchChannels }) => {
const onMessage = () => {
// TODO: Assumes only socket relationship is with channels. Actually flesh out socket logic
fetchChannels()
}
return (
<Websocket debug url='ws://localhost:3000/' onMessage={onMessage} />
)
}
Socket.propTypes = {
fetchChannels: PropTypes.func.isRequired
}
export default Socket

6
app/routes/wallet/components/components/Channels/components/ChannelForm/ChannelForm.js

@ -12,9 +12,9 @@ const ChannelForm = ({ form, setForm, ticker, peers, openChannel }) => {
const localamt = ticker.currency === 'btc' ? btc.btcToSatoshis(local_amt) : btc.btcToSatoshis(usd.usdToBtc(local_amt, ticker.btcTicker.price_usd)) const localamt = ticker.currency === 'btc' ? btc.btcToSatoshis(local_amt) : btc.btcToSatoshis(usd.usdToBtc(local_amt, ticker.btcTicker.price_usd))
const pushamt = ticker.currency === 'btc' ? btc.btcToSatoshis(push_amt) : btc.btcToSatoshis(usd.usdToBtc(push_amt, ticker.btcTicker.price_usd)) const pushamt = ticker.currency === 'btc' ? btc.btcToSatoshis(push_amt) : btc.btcToSatoshis(usd.usdToBtc(push_amt, ticker.btcTicker.price_usd))
openChannel({ pubkey: node_key, localamt, pushamt }).then((channel) => { openChannel({ pubkey: node_key, localamt, pushamt })
if (channel.data) { setForm({ isOpen: false }) } setForm({ isOpen: false })
})
} }
const customStyles = { const customStyles = {

5
app/routes/wallet/components/components/Peers/components/PeerForm/PeerForm.js

@ -6,10 +6,7 @@ import styles from './PeerForm.scss'
const PeerForm = ({ form, setForm, connect }) => { const PeerForm = ({ form, setForm, connect }) => {
const submit = () => { const submit = () => {
const { pubkey, host } = form const { pubkey, host } = form
connect({ pubkey, host })
connect({ pubkey, host }).then((success) => {
if (success.data) { setForm({ isOpen: false }) }
})
} }
const customStyles = { const customStyles = {

7
app/routes/wallet/components/components/Peers/components/PeerModal/PeerModal.js

@ -4,11 +4,6 @@ import ReactModal from 'react-modal'
import styles from './PeerModal.scss' import styles from './PeerModal.scss'
const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => { const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
const disconnectClicked = () => {
disconnect({ pubkey: peer.pub_key })
.then(success => (success ? resetPeer(null) : null))
}
const customStyles = { const customStyles = {
overlay: { overlay: {
cursor: 'pointer', cursor: 'pointer',
@ -55,7 +50,7 @@ const PeerModal = ({ isOpen, resetPeer, peer, disconnect }) => {
<dd>{peer.bytes_sent}</dd> <dd>{peer.bytes_sent}</dd>
</dl> </dl>
</div> </div>
<div className={styles.close} onClick={disconnectClicked}> <div className={styles.close} onClick={() => disconnect({ pubkey: peer.pub_key })}>
<div>Disconnect peer</div> <div>Disconnect peer</div>
</div> </div>
</div> </div>

1
package.json

@ -184,6 +184,7 @@
}, },
"dependencies": { "dependencies": {
"axios": "^0.16.2", "axios": "^0.16.2",
"bitcore-lib": "^0.14.0",
"devtron": "^1.4.0", "devtron": "^1.4.0",
"electron-debug": "^1.2.0", "electron-debug": "^1.2.0",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",

42
yarn.lock

@ -1485,6 +1485,17 @@ binary-extensions@^1.0.0:
buffers "~0.1.1" buffers "~0.1.1"
chainsaw "~0.1.0" chainsaw "~0.1.0"
bitcore-lib@^0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.14.0.tgz#21cb2359fe7b997a3b7b773eb7d7275ae37d644e"
dependencies:
bn.js "=2.0.4"
bs58 "=2.0.0"
buffer-compare "=1.0.0"
elliptic "=3.0.3"
inherits "=2.0.1"
lodash "=3.10.1"
bl@^1.0.0: bl@^1.0.0:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e"
@ -1507,6 +1518,14 @@ bluebird@^3.0.5, bluebird@^3.4.7, bluebird@^3.5.0:
version "3.5.0" version "3.5.0"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
bn.js@=2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.0.4.tgz#220a7cd677f7f1bfa93627ff4193776fe7819480"
bn.js@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625"
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.6" version "4.11.6"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
@ -1634,6 +1653,10 @@ browserslist@^1.1.1, browserslist@^1.1.3, browserslist@^1.3.6, browserslist@^1.5
caniuse-db "^1.0.30000639" caniuse-db "^1.0.30000639"
electron-to-chromium "^1.2.7" electron-to-chromium "^1.2.7"
bs58@=2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.0.tgz#72b713bed223a0ac518bbda0e3ce3f4817f39eb5"
bser@1.0.2: bser@1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169" resolved "https://registry.yarnpkg.com/bser/-/bser-1.0.2.tgz#381116970b2a6deea5646dd15dd7278444b56169"
@ -1646,6 +1669,10 @@ bser@^2.0.0:
dependencies: dependencies:
node-int64 "^0.4.0" node-int64 "^0.4.0"
buffer-compare@=1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.0.0.tgz#acaa7a966e98eee9fae14b31c39a5f158fb3c4a2"
buffer-crc32@^0.2.1: buffer-crc32@^0.2.1:
version "0.2.13" version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
@ -2969,6 +2996,15 @@ electron@^1.6.10:
electron-download "^3.0.1" electron-download "^3.0.1"
extract-zip "^1.0.3" extract-zip "^1.0.3"
elliptic@=3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-3.0.3.tgz#865c9b420bfbe55006b9f969f97a0d2c44966595"
dependencies:
bn.js "^2.0.0"
brorand "^1.0.1"
hash.js "^1.0.0"
inherits "^2.0.1"
elliptic@^6.0.0: elliptic@^6.0.0:
version "6.4.0" version "6.4.0"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
@ -4442,7 +4478,7 @@ inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, i
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
inherits@2.0.1: inherits@2.0.1, inherits@=2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
@ -5553,6 +5589,10 @@ lodash.uniq@^4.5.0:
version "4.5.0" version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
lodash@=3.10.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0, lodash@~4.17.4: lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0, lodash@~4.17.4:
version "4.17.4" version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"

Loading…
Cancel
Save