From d25d1dfa739223ec77c68e2c897d152a5381e73d Mon Sep 17 00:00:00 2001 From: Jack Mallers Date: Thu, 17 Aug 2017 17:46:34 -0500 Subject: [PATCH] feature(lnd-ipc): initial lnd + ipcRenderer setup w/ info as example --- app/lnd/config/index.js | 4 + app/lnd/config/rpc.proto | 690 +++++++++++++++++++++++++++++++ app/lnd/index.js | 18 + app/lnd/lib/lightning.js | 13 + app/main.dev.js | 16 +- app/reducers/info.js | 8 +- app/routes/app/components/App.js | 6 +- package.json | 2 + yarn.lock | 125 +++++- 9 files changed, 866 insertions(+), 16 deletions(-) create mode 100644 app/lnd/config/index.js create mode 100644 app/lnd/config/rpc.proto create mode 100644 app/lnd/index.js create mode 100644 app/lnd/lib/lightning.js diff --git a/app/lnd/config/index.js b/app/lnd/config/index.js new file mode 100644 index 00000000..e409c073 --- /dev/null +++ b/app/lnd/config/index.js @@ -0,0 +1,4 @@ +export default { + lightningRpc: `${__dirname}/rpc.proto`, + lightningHost: 'localhost:10009' +} diff --git a/app/lnd/config/rpc.proto b/app/lnd/config/rpc.proto new file mode 100644 index 00000000..f341e415 --- /dev/null +++ b/app/lnd/config/rpc.proto @@ -0,0 +1,690 @@ +syntax = "proto3"; + +//import "google/api/annotations.proto"; + +package lnrpc; + +service Lightning { + rpc WalletBalance (WalletBalanceRequest) returns (WalletBalanceResponse) { + option (google.api.http) = { + get: "/v1/balance/blockchain" + }; + } + rpc ChannelBalance (ChannelBalanceRequest) returns (ChannelBalanceResponse) { + option (google.api.http) = { + get: "/v1/balance/channels" + }; + } + + rpc GetTransactions (GetTransactionsRequest) returns (TransactionDetails) { + option (google.api.http) = { + get: "/v1/transactions" + }; + } + rpc SendCoins (SendCoinsRequest) returns (SendCoinsResponse) { + option (google.api.http) = { + post: "/v1/transactions" + body: "*" + }; + } + rpc SubscribeTransactions (GetTransactionsRequest) returns (stream Transaction); + + rpc SendMany (SendManyRequest) returns (SendManyResponse); + + rpc NewAddress (NewAddressRequest) returns (NewAddressResponse); + rpc NewWitnessAddress (NewWitnessAddressRequest) returns (NewAddressResponse) { + option (google.api.http) = { + get: "/v1/newaddress" + }; + } + + rpc SignMessage (SignMessageRequest) returns (SignMessageResponse); + rpc VerifyMessage (VerifyMessageRequest) returns (VerifyMessageResponse); + + rpc ConnectPeer (ConnectPeerRequest) returns (ConnectPeerResponse) { + option (google.api.http) = { + post: "/v1/peers" + body: "*" + }; + } + + rpc DisconnectPeer (DisconnectPeerRequest) returns (DisconnectPeerResponse) { + option (google.api.http) = { + delete: "/v1/peers/{pub_key}" + }; + } + + rpc ListPeers (ListPeersRequest) returns (ListPeersResponse) { + option (google.api.http) = { + get: "/v1/peers" + }; + } + rpc GetInfo (GetInfoRequest) returns (GetInfoResponse) { + option (google.api.http) = { + get: "/v1/getinfo" + }; + } + + // TODO(roasbeef): merge with below with bool? + rpc PendingChannels (PendingChannelRequest) returns (PendingChannelResponse) { + option (google.api.http) = { + get: "/v1/channels/pending" + }; + } + rpc ListChannels (ListChannelsRequest) returns (ListChannelsResponse) { + option (google.api.http) = { + get: "/v1/channels" + }; + } + rpc OpenChannelSync (OpenChannelRequest) returns (ChannelPoint) { + option (google.api.http) = { + post: "/v1/channels" + body: "*" + }; + } + + rpc OpenChannel (OpenChannelRequest) returns (stream OpenStatusUpdate); + + rpc CloseChannel (CloseChannelRequest) returns (stream CloseStatusUpdate) { + option (google.api.http) = { + delete: "/v1/channels/{channel_point.funding_txid}/{channel_point.output_index}/{force}" + }; + } + + rpc SendPayment (stream SendRequest) returns (stream SendResponse); + + rpc SendPaymentSync (SendRequest) returns (SendResponse) { + option (google.api.http) = { + post: "/v1/channels/transactions" + body: "*" + }; + } + + rpc AddInvoice (Invoice) returns (AddInvoiceResponse) { + option (google.api.http) = { + post: "/v1/invoices" + body: "*" + }; + } + rpc ListInvoices (ListInvoiceRequest) returns (ListInvoiceResponse) { + option (google.api.http) = { + get: "/v1/invoices/{pending_only}" + }; + } + rpc LookupInvoice (PaymentHash) returns (Invoice) { + option (google.api.http) = { + get: "/v1/invoices/{r_hash_str}" + }; + } + rpc SubscribeInvoices (InvoiceSubscription) returns (stream Invoice) { + option (google.api.http) = { + get: "/v1/invoices/subscribe" + }; + } + rpc DecodePayReq (PayReqString) returns (PayReq) { + option (google.api.http) = { + get: "/v1/payreq/{pay_req}" + }; + } + + rpc ListPayments (ListPaymentsRequest) returns (ListPaymentsResponse) { + option (google.api.http) = { + get: "/v1/payments" + }; + }; + + rpc DeleteAllPayments (DeleteAllPaymentsRequest) returns (DeleteAllPaymentsResponse) { + option (google.api.http) = { + delete: "/v1/payments" + }; + }; + + rpc DescribeGraph (ChannelGraphRequest) returns (ChannelGraph) { + option (google.api.http) = { + get: "/v1/graph" + }; + } + + rpc GetChanInfo (ChanInfoRequest) returns (ChannelEdge) { + option (google.api.http) = { + get: "/v1/graph/edge/{chan_id}" + }; + } + + rpc GetNodeInfo (NodeInfoRequest) returns (NodeInfo) { + option (google.api.http) = { + get: "/v1/graph/node/{pub_key}" + }; + } + + rpc QueryRoutes(QueryRoutesRequest) returns (QueryRoutesResponse) { + option (google.api.http) = { + get: "/v1/graph/routes/{pub_key}/{amt}" + }; + } + + rpc GetNetworkInfo (NetworkInfoRequest) returns (NetworkInfo) { + option (google.api.http) = { + get: "/v1/graph/info" + }; + } + + rpc StopDaemon(StopRequest) returns (StopResponse); + + rpc SubscribeChannelGraph(GraphTopologySubscription) returns (stream GraphTopologyUpdate); + + rpc SetAlias(SetAliasRequest) returns (SetAliasResponse); + + rpc DebugLevel (DebugLevelRequest) returns (DebugLevelResponse); +} + +message Transaction { + string tx_hash = 1 [ json_name = "tx_hash" ]; + int64 amount = 2 [ json_name = "amount" ]; + int32 num_confirmations = 3 [ json_name = "num_confirmations" ]; + string block_hash = 4 [ json_name = "block_hash" ]; + int32 block_height = 5 [ json_name = "block_height" ]; + int64 time_stamp = 6 [ json_name = "time_stamp" ]; + int64 total_fees = 7 [ json_name = "total_fees" ]; +} +message GetTransactionsRequest { +} +message TransactionDetails { + repeated Transaction transactions = 1 [json_name = "transactions"]; +} + +message SendRequest { + bytes dest = 1; + string dest_string = 2; + + int64 amt = 3; + + bytes payment_hash = 4; + string payment_hash_string = 5; + + string payment_request = 6; +} +message SendResponse { + string payment_error = 1 [json_name = "payment_error"]; + bytes payment_preimage = 2 [json_name = "payment_preimage"]; + Route payment_route = 3 [json_name = "payment_route"]; +} + +message ChannelPoint { + // TODO(roasbeef): make str vs bytes into a oneof + bytes funding_txid = 1 [ json_name = "funding_txid" ]; + string funding_txid_str = 2 [ json_name = "funding_txid_str" ]; + uint32 output_index = 3 [ json_name = "output_index" ]; +} + +message LightningAddress { + string pubkey = 1 [json_name = "pubkey"]; + string host = 2 [json_name = "host"]; +} + +message SendManyRequest { + map AddrToAmount = 1; +} +message SendManyResponse { + string txid = 1 [json_name = "txid"]; +} + +message SendCoinsRequest { + string addr = 1; + int64 amount = 2; +} +message SendCoinsResponse { + string txid = 1 [json_name = "txid"]; +} + +message NewAddressRequest { + enum AddressType { + WITNESS_PUBKEY_HASH = 0; + NESTED_PUBKEY_HASH = 1; + PUBKEY_HASH = 2; + } + AddressType type = 1; +} +message NewWitnessAddressRequest { +} +message NewAddressResponse { + string address = 1 [json_name = "address"]; +} + +message SignMessageRequest { + bytes msg = 1 [ json_name = "msg" ]; +} +message SignMessageResponse { + string signature = 1 [ json_name = "signature" ]; +} + +message VerifyMessageRequest { + bytes msg = 1 [ json_name = "msg" ]; + string signature = 2 [ json_name = "signature" ]; +} +message VerifyMessageResponse { + bool valid = 1 [ json_name = "valid" ]; + string pubkey = 2 [ json_name = "pubkey" ]; +} + +message ConnectPeerRequest { + LightningAddress addr = 1; + bool perm = 2; +} +message ConnectPeerResponse { + int32 peer_id = 1 [json_name = "peer_id"]; +} + +message DisconnectPeerRequest { + string pub_key = 1 [json_name = "pub_key"]; +} +message DisconnectPeerResponse { +} + +message HTLC { + bool incoming = 1 [json_name = "incoming"]; + int64 amount = 2 [json_name = "amount"]; + bytes hash_lock = 3 [json_name = "hash_lock"]; + uint32 expiration_height = 4 [json_name = "expiration_height"]; + uint32 revocation_delay = 5 [json_name = "revocation_delay"]; +} + +message ActiveChannel { + bool active = 1 [json_name = "active"]; + string remote_pubkey = 2 [json_name = "remote_pubkey"]; + string channel_point = 3 [json_name = "channel_point"]; + uint64 chan_id = 4 [json_name = "chan_id"]; + + int64 capacity = 5 [json_name = "capacity"]; + int64 local_balance = 6 [json_name = "local_balance"]; + int64 remote_balance = 7 [json_name = "remote_balance"]; + + int64 commit_fee = 8 [json_name = "commit_fee"]; + int64 commit_weight = 9 [ json_name = "commit_weight" ]; + int64 fee_per_kw = 10 [json_name = "fee_per_kw"]; + + int64 unsettled_balance = 11 [json_name = "unsettled_balance"]; + int64 total_satoshis_sent = 12 [json_name = "total_satoshis_sent"]; + int64 total_satoshis_received = 13 [json_name = "total_satoshis_received"]; + uint64 num_updates = 14 [json_name = "num_updates"]; + + repeated HTLC pending_htlcs = 15 [json_name = "pending_htlcs"]; +} + +message ListChannelsRequest { +} +message ListChannelsResponse { + repeated ActiveChannel channels = 11 [json_name = "channels"]; +} + +message Peer { + string pub_key = 1 [json_name = "pub_key"]; + int32 peer_id = 2 [json_name = "peer_id"]; + string address = 3 [json_name = "address"]; + + uint64 bytes_sent = 4 [json_name = "bytes_sent"]; + uint64 bytes_recv = 5 [json_name = "bytes_recv"]; + + int64 sat_sent = 6 [json_name = "sat_sent"]; + int64 sat_recv = 7 [json_name = "sat_recv"]; + + bool inbound = 8 [json_name = "inbound"]; + + int64 ping_time = 9 [json_name = "ping_time"]; +} + +message ListPeersRequest { +} +message ListPeersResponse { + repeated Peer peers = 1 [json_name = "peers"]; +} + +message GetInfoRequest { +} +message GetInfoResponse { + string identity_pubkey = 1 [json_name = "identity_pubkey"]; + string alias = 2 [json_name = "alias"]; + + uint32 num_pending_channels = 3 [json_name = "num_pending_channels"]; + uint32 num_active_channels = 4 [json_name = "num_active_channels"]; + + uint32 num_peers = 5 [json_name = "num_peers"]; + + uint32 block_height = 6 [json_name = "block_height"]; + string block_hash = 8 [json_name = "block_hash"]; + + bool synced_to_chain = 9 [ json_name = "synced_to_chain" ]; + bool testnet = 10 [ json_name = "testnet" ]; + + repeated string chains = 11 [ json_name = "chains" ]; +} + +message ConfirmationUpdate { + bytes block_sha = 1; + int32 block_height = 2; + + uint32 num_confs_left = 3; +} + +message ChannelOpenUpdate { + ChannelPoint channel_point = 1 [json_name = "channel_point"]; +} + +message ChannelCloseUpdate { + bytes closing_txid = 1 [json_name = "closing_txid"]; + + bool success = 2 [json_name = "success"]; +} + +message CloseChannelRequest { + ChannelPoint channel_point = 1; + int64 time_limit = 2; + bool force = 3; +} +message CloseStatusUpdate { + oneof update { + PendingUpdate close_pending = 1 [json_name = "close_pending"]; + ConfirmationUpdate confirmation = 2 [json_name = "confirmation"]; + ChannelCloseUpdate chan_close = 3 [json_name = "chan_close"]; + } +} + +message PendingUpdate { + bytes txid = 1 [json_name = "txid"]; + uint32 output_index = 2 [json_name = "output_index"]; +} + +message OpenChannelRequest { + int32 target_peer_id = 1 [json_name = "target_peer_id"]; + bytes node_pubkey = 2 [json_name = "node_pubkey"]; + string node_pubkey_string = 3 [json_name = "node_pubkey_string"]; + + int64 local_funding_amount = 4 [json_name = "local_funding_amount"]; + int64 push_sat = 5 [json_name = "push_sat"]; + + uint32 num_confs = 6 [json_name = "num_confs"]; +} +message OpenStatusUpdate { + oneof update { + PendingUpdate chan_pending = 1 [json_name = "chan_pending"]; + ConfirmationUpdate confirmation = 2 [json_name = "confirmation"]; + ChannelOpenUpdate chan_open = 3 [json_name = "chan_open"]; + } +} + +message PendingChannelRequest {} +message PendingChannelResponse { + message PendingChannel { + string remote_node_pub = 1 [ json_name = "remote_node_pub" ]; + string channel_point = 2 [ json_name = "channel_point" ]; + + int64 capacity = 3 [ json_name = "capacity" ]; + + int64 local_balance = 4 [ json_name = "local_balance" ]; + int64 remote_balance = 5 [ json_name = "remote_balance" ]; + } + + message PendingOpenChannel { + PendingChannel channel = 1 [ json_name = "channel" ]; + + uint32 confirmation_height = 2 [ json_name = "confirmation_height" ]; + uint32 blocks_till_open = 3 [ json_name = "blocks_till_open" ]; + + int64 commit_fee = 4 [json_name = "commit_fee" ]; + int64 commit_weight = 5 [ json_name = "commit_weight" ]; + int64 fee_per_kw = 6 [ json_name = "fee_per_kw" ]; + } + + message ClosedChannel { + PendingChannel channel = 1; + + string closing_txid = 2 [ json_name = "closing_txid" ]; + } + + message ForceClosedChannel { + PendingChannel channel = 1 [ json_name = "channel" ]; + + // TODO(roasbeef): HTLC's as well? + + string closing_txid = 2 [ json_name = "closing_txid" ]; + + int64 limbo_balance = 3 [ json_name = "limbo_balance" ]; + uint32 maturity_height = 4 [ json_name = "maturity_height" ]; + uint32 blocks_til_maturity = 5 [ json_name = "blocks_til_maturity" ]; + } + + int64 total_limbo_balance = 1 [ json_name = "total_limbo_balance" ]; + repeated PendingOpenChannel pending_open_channels = 2 [ json_name = "pending_open_channels" ]; + repeated ClosedChannel pending_closing_channels = 3 [ json_name = "pending_closing_channels" ]; + repeated ForceClosedChannel pending_force_closing_channels = 4 [ json_name = "pending_force_closing_channels" ]; +} + +message WalletBalanceRequest { + bool witness_only = 1; +} +message WalletBalanceResponse { + int64 balance = 1 [json_name = "balance"]; +} + +message ChannelBalanceRequest { +} +message ChannelBalanceResponse { + int64 balance = 1 [json_name = "balance"]; +} + +message QueryRoutesRequest { + string pub_key = 1; + int64 amt = 2; +} +message QueryRoutesResponse { + repeated Route routes = 1 [ json_name = "routes"]; +} + +message Hop { + uint64 chan_id = 1 [json_name = "chan_id"]; + int64 chan_capacity = 2 [json_name = "chan_capacity"]; + int64 amt_to_forward = 3 [json_name = "amt_to_forward"]; + int64 fee = 4 [json_name = "fee"]; +} + +message Route { + uint32 total_time_lock = 1 [json_name = "total_time_lock"]; + int64 total_fees = 2 [json_name = "total_fees"]; + int64 total_amt = 3 [json_name = "total_amt"]; + + repeated Hop hops = 4 [json_name = "hops"]; +} + +message NodeInfoRequest { + string pub_key = 1; +} + +message NodeInfo { + LightningNode node = 1 [json_name = "node"]; + + uint32 num_channels = 2 [json_name = "num_channels"]; + int64 total_capacity = 3 [json_name = "total_capacity"]; +} + +message LightningNode { + uint32 last_update = 1 [ json_name = "last_update" ]; + string pub_key = 2 [ json_name = "pub_key" ]; + string alias = 3 [ json_name = "alias" ]; + repeated NodeAddress addresses = 4 [ json_name = "addresses" ]; +} + +message NodeAddress { + string network = 1 [ json_name = "network" ]; + string addr = 2 [ json_name = "addr" ]; +} + +message RoutingPolicy { + uint32 time_lock_delta = 1 [json_name = "time_lock_delta"]; + int64 min_htlc = 2 [json_name = "min_htlc"]; + int64 fee_base_msat = 3 [json_name = "fee_base_msat"]; + int64 fee_rate_milli_msat = 4 [json_name = "fee_rate_milli_msat"]; +} + +message ChannelEdge { + uint64 channel_id = 1 [json_name = "channel_id"]; + string chan_point = 2 [json_name = "chan_point"]; + + uint32 last_update = 3 [json_name = "last_update"]; + + string node1_pub = 4 [json_name = "node1_pub"]; + string node2_pub = 5 [json_name = "node2_pub"]; + + int64 capacity = 6 [json_name = "capacity"]; + + RoutingPolicy node1_policy = 7 [json_name = "node1_policy"]; + RoutingPolicy node2_policy = 8 [json_name = "node2_policy"]; +} + +message ChannelGraphRequest { +} + +message ChannelGraph { + repeated LightningNode nodes = 1 [json_name = "nodes"]; + repeated ChannelEdge edges = 2 [json_name = "edges"]; +} + +message ChanInfoRequest { + uint64 chan_id = 1; +} + +message NetworkInfoRequest { +} +message NetworkInfo { + uint32 graph_diameter = 1 [json_name = "graph_diameter"]; + double avg_out_degree = 2 [json_name = "avg_out_degree"]; + uint32 max_out_degree = 3 [json_name = "max_out_degree"]; + + uint32 num_nodes = 4 [json_name = "num_nodes"]; + uint32 num_channels = 5 [json_name = "num_channels"]; + + int64 total_network_capacity = 6 [json_name = "total_network_capacity"]; + + double avg_channel_size = 7 [json_name = "avg_channel_size"]; + int64 min_channel_size = 8 [json_name = "min_channel_size"]; + int64 max_channel_size = 9 [json_name = "max_channel_size"]; + + // TODO(roasbeef): fee rate info, expiry + // * also additional RPC for tracking fee info once in +} + +message StopRequest{} +message StopResponse{} + +message GraphTopologySubscription {} +message GraphTopologyUpdate { + repeated NodeUpdate node_updates = 1; + repeated ChannelEdgeUpdate channel_updates = 2; + repeated ClosedChannelUpdate closed_chans = 3; +} +message NodeUpdate { + repeated string addresses = 1; + string identity_key = 2; + bytes global_features = 3; + string alias = 4; +} +message ChannelEdgeUpdate { + uint64 chan_id = 1; + + ChannelPoint chan_point = 2; + + int64 capacity = 3; + + RoutingPolicy routing_policy = 4; + + string advertising_node = 5; + string connecting_node = 6; +} +message ClosedChannelUpdate { + uint64 chan_id = 1; + int64 capacity = 2; + uint32 closed_height = 3; + ChannelPoint chan_point = 4; +} + +message SetAliasRequest { + string new_alias = 1; +} +message SetAliasResponse { +} + +message Invoice { + string memo = 1 [json_name = "memo"]; + bytes receipt = 2 [json_name = "receipt"]; + + bytes r_preimage = 3 [json_name = "r_preimage"]; + bytes r_hash = 4 [json_name = "r_hash"]; + + int64 value = 5 [json_name = "value"]; + + bool settled = 6 [json_name = "settled"]; + + int64 creation_date = 7 [json_name = "creation_date"]; + int64 settle_date = 8 [json_name = "settle_date"]; + + string payment_request = 9 [json_name = "payment_request"]; +} +message AddInvoiceResponse { + bytes r_hash = 1 [json_name = "r_hash"]; + + string payment_request = 2 [json_name = "payment_request"]; +} +message PaymentHash { + string r_hash_str = 1 [json_name = "r_hash_str"]; + bytes r_hash = 2 [json_name = "r_hash"]; +} +message ListInvoiceRequest { + bool pending_only = 1; +} +message ListInvoiceResponse { + repeated Invoice invoices = 1 [json_name = "invoices"]; +} + +message InvoiceSubscription { +} + + +message Payment { + string payment_hash = 1 [json_name = "payment_hash"]; + int64 value = 2 [json_name = "value"]; + + int64 creation_date = 3 [json_name = "creation_date"]; + + repeated string path = 4 [ json_name = "path" ]; + + int64 fee = 5 [json_name = "fee"]; +} + +message ListPaymentsRequest { +} + +message ListPaymentsResponse { + repeated Payment payments = 1 [json_name = "payments"]; +} + +message DeleteAllPaymentsRequest { +} + +message DeleteAllPaymentsResponse { +} + +message DebugLevelRequest { + bool show = 1; + string level_spec = 2; +} +message DebugLevelResponse { + string sub_systems = 1 [json_name = "sub_systems"]; +} + +message PayReqString { + string pay_req = 1; +} +message PayReq { + string destination = 1 [json_name = "destination"]; + string payment_hash = 2 [json_name = "payment_hash"]; + int64 num_satoshis = 3 [json_name = "num_satoshis"]; +} \ No newline at end of file diff --git a/app/lnd/index.js b/app/lnd/index.js new file mode 100644 index 00000000..7ec9df01 --- /dev/null +++ b/app/lnd/index.js @@ -0,0 +1,18 @@ +import config from './config' +import lightning from './lib/lightning' + +const lnd = lightning(config.lightningRpc, config.lightningHost) + +export function info() { + return new Promise((resolve, reject) => { + lnd.getInfo({}, (err, data) => { + if (err) { reject(err) } + + resolve(data) + }) + }) +} + +export default { + info +} \ No newline at end of file diff --git a/app/lnd/lib/lightning.js b/app/lnd/lib/lightning.js new file mode 100644 index 00000000..fb8cdc1e --- /dev/null +++ b/app/lnd/lib/lightning.js @@ -0,0 +1,13 @@ +import fs from 'fs' +import grpc from 'grpc' + +module.exports = (path, host, cert) => { + process.env['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA' + + const rpc = grpc.load(path) + + const lndCert = fs.readFileSync('/Users/jmow/Library/Application Support/Lnd/tls.cert') + const credentials = grpc.credentials.createSsl(lndCert) + + return new rpc.lnrpc.Lightning(host, credentials) +} \ No newline at end of file diff --git a/app/main.dev.js b/app/main.dev.js index c5f4c8df..b78b0c3f 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -11,8 +11,9 @@ * * @flow */ -import { app, BrowserWindow } from 'electron' +import { app, BrowserWindow, ipcMain } from 'electron' import MenuBuilder from './menu' +import lnd from './lnd' let mainWindow = null; @@ -90,3 +91,16 @@ app.on('ready', async () => { const menuBuilder = new MenuBuilder(mainWindow); menuBuilder.buildMenu(); }); + +ipcMain.on('lnd', (event, { msg, data }) => { + switch(msg) { + case 'info': + lnd.info() + .then(data => event.sender.send('info', data)) + .catch(error => console.log('info error: ', error)) + break + default: + return + } +}) + diff --git a/app/reducers/info.js b/app/reducers/info.js index 2cf7bef4..075e9d8d 100644 --- a/app/reducers/info.js +++ b/app/reducers/info.js @@ -1,3 +1,4 @@ +import { ipcRenderer } from 'electron' import { callApi } from '../api' // ------------------------------------ // Constants @@ -23,8 +24,11 @@ export function receiveInfo(data) { export const fetchInfo = () => async (dispatch) => { dispatch(getInfo()) - const info = await callApi('info') - dispatch(receiveInfo(info.data)) + ipcRenderer.send('lnd', { msg: 'info' }) + ipcRenderer.on('info', (event, info) => { + dispatch(receiveInfo(info)) + }) + // const info = await callApi('info') } // ------------------------------------ diff --git a/app/routes/app/components/App.js b/app/routes/app/components/App.js index e125e70d..61eed04c 100644 --- a/app/routes/app/components/App.js +++ b/app/routes/app/components/App.js @@ -1,3 +1,4 @@ +import { ipcRenderer } from 'electron' import React, { Component } from 'react' import PropTypes from 'prop-types' import Form from './components/Form' @@ -5,11 +6,6 @@ import Nav from './components/Nav' import Socket from './components/Socket' import styles from './App.scss' -export const CHANNEL_DATA = 'CHANNEL_DATA' -export const CHANNEL_END = 'CHANNEL_END' -export const CHANNEL_ERROR = 'CHANNEL_ERROR' -export const CHANNEL_STATUS = 'CHANNEL_STATUS' - class App extends Component { componentWillMount() { const { fetchTicker, fetchBalance } = this.props diff --git a/package.json b/package.json index 334aea19..6c0a05c8 100644 --- a/package.json +++ b/package.json @@ -137,6 +137,7 @@ "electron": "^1.6.10", "electron-builder": "^19.8.0", "electron-devtools-installer": "^2.2.0", + "electron-rebuild": "^1.6.0", "enzyme": "^2.9.1", "enzyme-to-json": "^1.5.1", "eslint": "^4.4.1", @@ -186,6 +187,7 @@ "devtron": "^1.4.0", "electron-debug": "^1.2.0", "font-awesome": "^4.7.0", + "grpc": "^1.4.1", "history": "^4.6.3", "moment-timezone": "^0.5.13", "prop-types": "^15.5.10", diff --git a/yarn.lock b/yarn.lock index 571df020..5368e9ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -246,6 +246,10 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +arguejs@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/arguejs/-/arguejs-0.2.3.tgz#b6f939f5fe0e3cd1f3f93e2aa9262424bf312af7" + aria-query@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-0.7.0.tgz#4af10a1e61573ddea0cf3b99b51c52c05b424d24" @@ -322,6 +326,13 @@ asar-integrity@0.1.1: bluebird-lst "^1.0.2" fs-extra-p "^4.3.0" +ascli@~1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ascli/-/ascli-1.0.1.tgz#bcfa5974a62f18e81cabaeb49732ab4a88f906bc" + dependencies: + colour "~0.7.1" + optjs "~3.2.2" + asn1.js@^4.0.0: version "4.9.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.1.tgz#48ba240b45a9280e94748990ba597d216617fd40" @@ -1667,6 +1678,12 @@ builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" +bytebuffer@~5: + version "5.0.1" + resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd" + dependencies: + long "~3" + bytes@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.3.0.tgz#d5b680a165b6201739acb611542aabc2d8ceb070" @@ -1703,7 +1720,7 @@ camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" -camelcase@^2.0.0: +camelcase@^2.0.0, camelcase@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" @@ -1873,6 +1890,10 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-spinners@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.0.0.tgz#ef987ed3d48391ac3dab9180b406a742180d6e6a" + cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" @@ -1885,7 +1906,7 @@ cliui@^2.1.0: right-align "^0.1.1" wordwrap "0.0.2" -cliui@^3.2.0: +cliui@^3.0.3, cliui@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" dependencies: @@ -1990,6 +2011,10 @@ colors@^1.1.2, colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" +colour@~0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/colour/-/colour-0.7.1.tgz#9cb169917ec5d12c0736d3e8685746df1cadf778" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -2476,7 +2501,7 @@ debug@2.6.7: dependencies: ms "2.0.0" -debug@2.6.8, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.4.5, debug@^2.6.0, debug@^2.6.1, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8: +debug@2.6.8, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.4.5, debug@^2.5.1, debug@^2.6.0, debug@^2.6.1, debug@^2.6.3, debug@^2.6.6, debug@^2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: @@ -2918,6 +2943,20 @@ electron-publish@19.8.0: fs-extra-p "^4.3.0" mime "^1.3.6" +electron-rebuild@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/electron-rebuild/-/electron-rebuild-1.6.0.tgz#e8d26f4d8e9fe5388df35864b3658e5cfd4dcb7e" + dependencies: + colors "^1.1.2" + debug "^2.6.3" + fs-extra "^3.0.1" + node-abi "^2.0.0" + node-gyp "^3.6.0" + ora "^1.2.0" + rimraf "^2.6.1" + spawn-rx "^2.0.10" + yargs "^7.0.2" + electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.11: version "1.3.14" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.14.tgz#64af0f9efd3c3c6acd57d71f83b49ca7ee9c4b43" @@ -4024,6 +4063,16 @@ growly@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" +grpc@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/grpc/-/grpc-1.4.1.tgz#3ee4a8346a613f2823928c9f8f99081b6368ec7c" + dependencies: + arguejs "^0.2.3" + lodash "^4.15.0" + nan "^2.0.0" + node-pre-gyp "^0.6.35" + protobufjs "^5.0.0" + gulp-util@^3.0.4: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" @@ -5518,6 +5567,10 @@ lolex@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" +long@~3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b" + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -5789,7 +5842,7 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.3.0, nan@^2.3.2: +nan@^2.0.0, nan@^2.3.0, nan@^2.3.2: version "2.6.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" @@ -5821,6 +5874,10 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" +node-abi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.1.0.tgz#50ad834affcf17440e12bfc5f9ba0946f572d10c" + node-emoji@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.5.1.tgz#fd918e412769bf8c448051238233840b2aff16a1" @@ -5838,7 +5895,7 @@ node-forge@0.6.33: version "0.6.33" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc" -node-gyp@^3.3.1: +node-gyp@^3.3.1, node-gyp@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" dependencies: @@ -5925,7 +5982,7 @@ node-notifier@^5.0.2: shellwords "^0.1.0" which "^1.2.12" -node-pre-gyp@^0.6.29: +node-pre-gyp@^0.6.29, node-pre-gyp@^0.6.35: version "0.6.36" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" dependencies: @@ -6182,6 +6239,19 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" +optjs@~3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/optjs/-/optjs-3.2.2.tgz#69a6ce89c442a44403141ad2f9b370bd5bb6f4ee" + +ora@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-1.3.0.tgz#80078dd2b92a934af66a3ad72a5b910694ede51a" + dependencies: + chalk "^1.1.1" + cli-cursor "^2.1.0" + cli-spinners "^1.0.0" + log-symbols "^1.0.2" + original@>=0.0.5: version "1.0.0" resolved "https://registry.yarnpkg.com/original/-/original-1.0.0.tgz#9147f93fa1696d04be61e01bd50baeaca656bd3b" @@ -6828,6 +6898,15 @@ prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.8: fbjs "^0.8.9" loose-envify "^1.3.1" +protobufjs@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-5.0.2.tgz#59748d7dcf03d2db22c13da9feb024e16ab80c91" + dependencies: + ascli "~1" + bytebuffer "~5" + glob "^7.0.5" + yargs "^3.10.0" + proxy-addr@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3" @@ -7479,6 +7558,12 @@ rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" +rxjs@^5.1.1: + version "5.4.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.3.tgz#0758cddee6033d68e0fd53676f0f3596ce3d483f" + dependencies: + symbol-observable "^1.0.1" + safe-buffer@^5.0.1, safe-buffer@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.0.tgz#fe4c8460397f9eaaaa58e73be46273408a45e223" @@ -7793,6 +7878,14 @@ spawn-command@^0.0.2-1: version "0.0.2" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" +spawn-rx@^2.0.10: + version "2.0.11" + resolved "https://registry.yarnpkg.com/spawn-rx/-/spawn-rx-2.0.11.tgz#65451ad65662801daea75549832a782de0048dbf" + dependencies: + debug "^2.5.1" + lodash.assign "^4.2.0" + rxjs "^5.1.1" + spdx-correct@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" @@ -8228,7 +8321,7 @@ svgpath@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/svgpath/-/svgpath-2.2.1.tgz#0834bb67c89a76472b2bd06cc101fa7b517b222c" -symbol-observable@^1.0.3: +symbol-observable@^1.0.1, symbol-observable@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" @@ -8948,6 +9041,10 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" +window-size@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" + window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" @@ -9033,7 +9130,7 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -y18n@^3.2.1: +y18n@^3.2.0, y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" @@ -9070,6 +9167,18 @@ yargs@^1.2.6: version "1.3.3" resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.3.3.tgz#054de8b61f22eefdb7207059eaef9d6b83fb931a" +yargs@^3.10.0: + version "3.32.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" + dependencies: + camelcase "^2.0.1" + cliui "^3.0.3" + decamelize "^1.1.1" + os-locale "^1.4.0" + string-width "^1.0.1" + window-size "^0.1.4" + y18n "^3.2.0" + yargs@^3.5.4, yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"