balanceofsatoshis 10.16.2 → 10.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Versions
2
2
 
3
+ ## Version 10.17.0
4
+
5
+ - `chart-fees-paid`: Add tag icons to nodes in table view
6
+ - `telegram`: Add `/costs` command to report rebalance and chain fees
7
+
3
8
  ## Version 10.16.2
4
9
 
5
10
  - `chart-chain-fees`: Add mempool space chain fee lookup redundancy
package/README.md CHANGED
@@ -227,7 +227,12 @@ Use any shorthand you'd like when choosing this profile node name
227
227
 
228
228
  #### Umbrel Saved Node
229
229
 
230
- Note: Umbrel is not FOSS software, use at your own risk.
230
+ *Note: Umbrel is not FOSS software, use at your own risk.*
231
+
232
+ If you are using Umbrel and you have already installed but you get an error like
233
+ `Name resolution failed for target dns:umbrel.local:10009` then try adding umbrel.local
234
+ to your `/etc/hosts` file, like `sudo nano /etc/hosts` and add a line
235
+ `127.0.0.1 umbrel.local`
231
236
 
232
237
  1. Identify your Umbrel home dir, like /home/umbrel/umbrel
233
238
  2. Look in the .env file in that dir for the `LND_IP` to use as the socket to connect to
package/bos CHANGED
@@ -358,6 +358,7 @@ prog
358
358
  try {
359
359
  return routing.getFeesPaid({
360
360
  days: options.days,
361
+ fs: {getFile: readFile},
361
362
  is_most_fees_table: options.mostFees,
362
363
  is_most_forwarded_table: options.mostForwarded,
363
364
  is_network: options.network,
package/package.json CHANGED
@@ -35,9 +35,9 @@
35
35
  "inquirer": "8.1.5",
36
36
  "invoices": "2.0.0",
37
37
  "ln-accounting": "5.0.3",
38
- "ln-service": "52.4.0",
39
- "ln-sync": "1.0.0",
40
- "ln-telegram": "3.2.11",
38
+ "ln-service": "52.5.0",
39
+ "ln-sync": "2.0.0",
40
+ "ln-telegram": "3.3.0",
41
41
  "moment": "2.29.1",
42
42
  "paid-services": "2.1.1",
43
43
  "probing": "1.3.6",
@@ -80,5 +80,5 @@
80
80
  "postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis --push .",
81
81
  "test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -t 60 test/arrays/*.js test/balances/*.js test/chain/*.js test/display/*.js test/encryption/*.js test/fiat/*.js test/lnd/*.js test/network/*.js test/nodes/*.js test/peers/*.js test/responses/*.js test/routing/*.js test/services/*.js test/swaps/*.js test/tags/*.js test/wallets/*.js"
82
82
  },
83
- "version": "10.16.2"
83
+ "version": "10.17.0"
84
84
  }
@@ -3,11 +3,13 @@ const asyncMap = require('async/map');
3
3
  const {getNode} = require('ln-service');
4
4
  const {getChannels} = require('ln-service');
5
5
  const {getPayments} = require('ln-sync');
6
+ const {getRebalancePayments} = require('ln-sync');
6
7
  const moment = require('moment');
7
8
  const {returnResult} = require('asyncjs-util');
8
9
 
10
+ const {chartAliasForPeer} = require('./../display');
9
11
  const feesForSegment = require('./fees_for_segment');
10
- const getRebalancePayments = require('./get_rebalance_payments');
12
+ const {getIcons} = require('./../display');
11
13
  const {sortBy} = require('./../arrays');
12
14
 
13
15
  const by = 'confirmed_at';
@@ -27,6 +29,9 @@ const tokensAsBigUnit = tokens => (tokens / 1e8).toFixed(8);
27
29
 
28
30
  {
29
31
  days: <Fees Earned Over Days Count Number>
32
+ fs: {
33
+ getFile: <Read File Contents Function> (path, cbk) => {}
34
+ }
30
35
  [is_most_fees_table]: <Is Most Fees Table Bool>
31
36
  [is_most_forwarded_table]: <Is Most Forwarded Bool>
32
37
  [is_network]: <Show Only Non-Peers In Table Bool>
@@ -50,6 +55,10 @@ module.exports = (args, cbk) => {
50
55
  return cbk([400, 'ExpectedNumberOfDaysToGetFeesOverForChart']);
51
56
  }
52
57
 
58
+ if (!args.fs) {
59
+ return cbk([400, 'ExpectedFsMethodsToGetRoutingFeesPaid']);
60
+ }
61
+
53
62
  if (!!args.is_network && !!args.is_peer) {
54
63
  return cbk([400, 'ExpectedEitherNetworkOrPeersNotBoth']);
55
64
  }
@@ -75,6 +84,9 @@ module.exports = (args, cbk) => {
75
84
  });
76
85
  }],
77
86
 
87
+ // Get node icons
88
+ getIcons: ['validate', ({}, cbk) => getIcons({fs: args.fs}, cbk)],
89
+
78
90
  // Segment measure
79
91
  measure: ['validate', ({}, cbk) => {
80
92
  if (args.days > maxChartDays) {
@@ -130,7 +142,12 @@ module.exports = (args, cbk) => {
130
142
  }],
131
143
 
132
144
  // Fees paid to specific forwarding peers
133
- rows: ['forwards', 'getChannels', ({forwards, getChannels}, cbk) => {
145
+ rows: [
146
+ 'forwards',
147
+ 'getChannels',
148
+ 'getIcons',
149
+ ({forwards, getChannels, getIcons}, cbk) =>
150
+ {
134
151
  if (!args.is_most_forwarded_table && !args.is_most_fees_table) {
135
152
  return cbk();
136
153
  }
@@ -224,12 +241,22 @@ module.exports = (args, cbk) => {
224
241
 
225
242
  return !!args.is_peer ? isPeer : !isPeer;
226
243
  })
227
- .map(n => {
244
+ .map(node => {
245
+ const key = node.public_key;
246
+
247
+ const nodeIcons = getIcons.nodes.find(n => n.public_key === key);
248
+
249
+ const {display} = chartAliasForPeer({
250
+ alias: node.alias || ' ',
251
+ icons: !!nodeIcons ? nodeIcons.icons : undefined,
252
+ public_key: key,
253
+ });
254
+
228
255
  return [
229
- n.alias,
230
- n.public_key,
231
- mtokensAsBigUnit(n.fees_paid),
232
- mtokensAsBigUnit(n.forwarded),
256
+ display,
257
+ key,
258
+ mtokensAsBigUnit(node.fees_paid),
259
+ mtokensAsBigUnit(node.forwarded),
233
260
  ];
234
261
  });
235
262
 
@@ -13,6 +13,7 @@ const {getWalletInfo} = require('ln-service');
13
13
  const {handleBackupCommand} = require('ln-telegram');
14
14
  const {handleBlocknotifyCommand} = require('ln-telegram');
15
15
  const {handleConnectCommand} = require('ln-telegram');
16
+ const {handleCostsCommand} = require('ln-telegram');
16
17
  const {handleEarningsCommand} = require('ln-telegram');
17
18
  const {handleInvoiceCommand} = require('ln-telegram');
18
19
  const {handleLiquidityCommand} = require('ln-telegram');
@@ -194,6 +195,7 @@ module.exports = ({fs, id, limits, lnds, logger, payments, request}, cbk) => {
194
195
  {command: 'backup', description: 'Get node backup file'},
195
196
  {command: 'blocknotify', description: 'Get notified on next block'},
196
197
  {command: 'connect', description: 'Get connect code for the bot'},
198
+ {command: 'costs', description: 'Show costs over the week'},
197
199
  {command: 'earnings', description: 'Show earnings over the week'},
198
200
  {command: 'invoice', description: 'Create an invoice'},
199
201
  {command: 'liquidity', description: 'Get liquidity [with-peer]'},
@@ -272,14 +274,27 @@ module.exports = ({fs, id, limits, lnds, logger, payments, request}, cbk) => {
272
274
  return;
273
275
  });
274
276
 
277
+ bot.command('costs', ctx => {
278
+ handleCostsCommand({
279
+ request,
280
+ from: ctx.message.from.id,
281
+ id: connectedId,
282
+ nodes: allNodes,
283
+ reply: n => ctx.replyWithMarkdown(n),
284
+ working: () => ctx.replyWithChatAction('typing'),
285
+ },
286
+ err => !!err && !!err[0] >= 500 ? logger.error({err}) : null);
287
+
288
+ return;
289
+ });
290
+
275
291
  bot.command('earnings', ctx => {
276
292
  handleEarningsCommand({
277
293
  from: ctx.message.from.id,
278
294
  id: connectedId,
279
- key: apiKey.key,
280
295
  nodes: allNodes,
281
296
  reply: n => ctx.replyWithMarkdown(n),
282
- text: ctx.message.text,
297
+ working: () => ctx.replyWithChatAction('typing'),
283
298
  },
284
299
  err => !!err && !!err[0] >= 500 ? logger.error({err}) : null);
285
300
 
@@ -397,6 +412,7 @@ module.exports = ({fs, id, limits, lnds, logger, payments, request}, cbk) => {
397
412
  '/backup - Get node backup file',
398
413
  '/blocknotify - Notification on next block',
399
414
  '/connect - Connect bot',
415
+ '/costs - View costs over the past week',
400
416
  '/earnings - View earnings over the past week',
401
417
  '/invoice - Make an invoice',
402
418
  '/liquidity [with] - View node liquidity',
@@ -3,11 +3,11 @@ const asyncDetect = require('async/detect');
3
3
  const asyncFilterLimit = require('async/filterLimit');
4
4
  const asyncMap = require('async/map');
5
5
  const {formatTokens} = require('ln-sync');
6
+ const {getAllInvoices} = require('ln-sync');
6
7
  const {getPayment} = require('ln-service');
7
8
  const moment = require('moment');
8
9
  const {returnResult} = require('asyncjs-util');
9
10
 
10
- const getAllInvoices = require('./get_all_invoices');
11
11
  const {segmentMeasure} = require('./../display');
12
12
  const {sumsForSegment} = require('./../display');
13
13
 
package/wallets/index.js CHANGED
@@ -1,6 +1,5 @@
1
- const getAllInvoices = require('./get_all_invoices');
2
1
  const getReceivedChart = require('./get_received_chart');
3
2
  const getReport = require('./get_report');
4
3
  const unlockWallet = require('./unlock_wallet');
5
4
 
6
- module.exports = {getAllInvoices, getReceivedChart, getReport, unlockWallet};
5
+ module.exports = {getReceivedChart, getReport, unlockWallet};
@@ -1,162 +0,0 @@
1
- const asyncAuto = require('async/auto');
2
- const asyncMap = require('async/map');
3
- const asyncMapLimit = require('async/mapLimit');
4
- const {getPayment} = require('ln-service');
5
- const {returnResult} = require('asyncjs-util');
6
-
7
- const getAllInvoices = require('./../wallets/get_all_invoices');
8
-
9
- const flatten = arr => [].concat(...arr);
10
- const {isArray} = Array;
11
- const maxGetPayments = 100;
12
- const notFound = 404;
13
-
14
- /** Get payments that were rebalances
15
-
16
- {
17
- after: <Rebalance Payments After ISO 8601 Date String>
18
- lnds: [<Authenticated LND API Object>]
19
- }
20
-
21
- @returns via cbk or Promise
22
- {
23
- payments: [{
24
- attempts: [{
25
- [failure]: {
26
- code: <Error Type Code Number>
27
- [details]: {
28
- [channel]: <Standard Format Channel Id String>
29
- [height]: <Error Associated Block Height Number>
30
- [index]: <Failed Hop Index Number>
31
- [mtokens]: <Error Millitokens String>
32
- [policy]: {
33
- base_fee_mtokens: <Base Fee Millitokens String>
34
- cltv_delta: <Locktime Delta Number>
35
- fee_rate: <Fees Charged in Millitokens Per Million Number>
36
- [is_disabled]: <Channel is Disabled Bool>
37
- max_htlc_mtokens: <Maximum HLTC Millitokens Value String>
38
- min_htlc_mtokens: <Minimum HTLC Millitokens Value String>
39
- updated_at: <Updated At ISO 8601 Date String>
40
- }
41
- [timeout_height]: <Error CLTV Timeout Height Number>
42
- [update]: {
43
- chain: <Chain Id Hex String>
44
- channel_flags: <Channel Flags Number>
45
- extra_opaque_data: <Extra Opaque Data Hex String>
46
- message_flags: <Message Flags Number>
47
- signature: <Channel Update Signature Hex String>
48
- }
49
- }
50
- message: <Error Message String>
51
- }
52
- [index]: <Payment Add Index Number>
53
- [confirmed_at]: <Payment Confirmed At ISO 8601 Date String>
54
- is_confirmed: <Payment Attempt Succeeded Bool>
55
- is_failed: <Payment Attempt Failed Bool>
56
- is_pending: <Payment Attempt is Waiting For Resolution Bool>
57
- route: {
58
- fee: <Route Fee Tokens Number>
59
- fee_mtokens: <Route Fee Millitokens String>
60
- hops: [{
61
- channel: <Standard Format Channel Id String>
62
- channel_capacity: <Channel Capacity Tokens Number>
63
- fee: <Fee Number>
64
- fee_mtokens: <Fee Millitokens String>
65
- forward: <Forward Tokens Number>
66
- forward_mtokens: <Forward Millitokens String>
67
- [public_key]: <Forward Edge Public Key Hex String>
68
- [timeout]: <Timeout Block Height Number>
69
- }]
70
- mtokens: <Total Fee-Inclusive Millitokens String>
71
- [payment]: <Payment Identifier Hex String>
72
- timeout: <Timeout Block Height Number>
73
- tokens: <Total Fee-Inclusive Tokens Number>
74
- [total_mtokens]: <Total Millitokens String>
75
- }
76
- }]
77
- confirmed_at: <Payment Confirmed At ISO 8601 Date String>
78
- created_at: <Payment at ISO-8601 Date String>
79
- destination: <Destination Node Public Key Hex String>
80
- fee: <Paid Routing Fee Rounded Down Tokens Number>
81
- fee_mtokens: <Paid Routing Fee in Millitokens String>
82
- hops: [<First Route Hop Public Key Hex String>]
83
- id: <Payment Preimage Hash String>
84
- [index]: <Payment Add Index Number>
85
- is_confirmed: <Payment is Confirmed Bool>
86
- is_outgoing: <Transaction Is Outgoing Bool>
87
- mtokens: <Millitokens Sent to Destination String>
88
- [request]: <BOLT 11 Payment Request String>
89
- safe_fee: <Payment Forwarding Fee Rounded Up Tokens Number>
90
- safe_tokens: <Payment Tokens Rounded Up Number>
91
- secret: <Payment Preimage Hex String>
92
- tokens: <Rounded Down Tokens Sent to Destination Number>
93
- }]
94
- }
95
- */
96
- module.exports = ({after, lnds}, cbk) => {
97
- return new Promise((resolve, reject) => {
98
- return asyncAuto({
99
- // Check arguments
100
- validate: cbk => {
101
- if (!after) {
102
- return cbk([400, 'ExpectedAfterDateToGetRebalancePayments']);
103
- }
104
-
105
- if (!isArray(lnds)) {
106
- return cbk([400, 'ExpectedArrayOfLndsToGetRebalancePayments']);
107
- }
108
-
109
- return cbk();
110
- },
111
-
112
- // Get all the settled invoices
113
- getSettled: ['validate', ({}, cbk) => {
114
- return asyncMap(lnds, (lnd, cbk) => {
115
- return getAllInvoices({lnd, created_after: after}, cbk);
116
- },
117
- (err, res) => {
118
- if (!!err) {
119
- return cbk(err);
120
- }
121
-
122
- return cbk(null, flatten(res.map(({invoices}) => invoices)));
123
- });
124
- }],
125
-
126
- // Find self-payments by looking for payments with invoice ids
127
- getRebalances: ['getSettled', ({getSettled}, cbk) => {
128
- return asyncMap(lnds, (lnd, cbk) => {
129
- return asyncMapLimit(getSettled, maxGetPayments, ({id}, cbk) => {
130
- return getPayment({id, lnd}, (err, res) => {
131
- // Exit early when there is no matching payment
132
- if (isArray(err) && err.shift() === notFound) {
133
- return cbk();
134
- }
135
-
136
- if (!!err) {
137
- return cbk(err);
138
- }
139
-
140
- return cbk(null, res.payment);
141
- });
142
- },
143
- (err, payments) => {
144
- if (!!err) {
145
- return cbk(err);
146
- }
147
-
148
- return cbk(null, payments.filter(n => !!n));
149
- });
150
- },
151
- (err, res) => {
152
- if (!!err) {
153
- return cbk(err);
154
- }
155
-
156
- return cbk(null, {payments: flatten(res)});
157
- });
158
- }],
159
- },
160
- returnResult({reject, resolve, of: 'getRebalances'}, cbk));
161
- });
162
- };
@@ -1,125 +0,0 @@
1
- const asyncAuto = require('async/auto');
2
- const asyncUntil = require('async/until');
3
- const {returnResult} = require('asyncjs-util');
4
-
5
- const {getInvoices} = require('ln-service');
6
-
7
- const defaultInvoicesLimit = 100;
8
-
9
- /** Get all invoices
10
-
11
- {
12
- [confirmed_after]: <Confirmed At or After ISO 8601 Date String>
13
- [created_after]: <Confirmed At or After ISO 8601 Date String>
14
- lnd: <Authenticated LND API Object>
15
- }
16
-
17
- @returns via cbk or Promise
18
- {
19
- invoices: [{
20
- [chain_address]: <Fallback Chain Address String>
21
- cltv_delta: <Final CLTV Delta Number>
22
- [confirmed_at]: <Settled at ISO 8601 Date String>
23
- created_at: <ISO 8601 Date String>
24
- description: <Description String>
25
- [description_hash]: <Description Hash Hex String>
26
- expires_at: <ISO 8601 Date String>
27
- features: [{
28
- bit: <BOLT 09 Feature Bit Number>
29
- is_known: <Feature is Known Bool>
30
- is_required: <Feature Support is Required To Pay Bool>
31
- type: <Feature Type String>
32
- }]
33
- id: <Payment Hash String>
34
- [is_canceled]: <Invoice is Canceled Bool>
35
- is_confirmed: <Invoice is Confirmed Bool>
36
- [is_held]: <HTLC is Held Bool>
37
- is_private: <Invoice is Private Bool>
38
- [is_push]: <Invoice is Push Payment Bool>
39
- payments: [{
40
- [confirmed_at]: <Payment Settled At ISO 8601 Date String>
41
- created_at: <Payment Held Since ISO 860 Date String>
42
- created_height: <Payment Held Since Block Height Number>
43
- in_channel: <Incoming Payment Through Channel Id String>
44
- is_canceled: <Payment is Canceled Bool>
45
- is_confirmed: <Payment is Confirmed Bool>
46
- is_held: <Payment is Held Bool>
47
- messages: [{
48
- type: <Message Type Number String>
49
- value: <Raw Value Hex String>
50
- }]
51
- mtokens: <Incoming Payment Millitokens String>
52
- [pending_index]: <Pending Payment Channel HTLC Index Number>
53
- tokens: <Payment Tokens Number>
54
- [total_mtokens]: <Total Millitokens String>
55
- }]
56
- received: <Received Tokens Number>
57
- received_mtokens: <Received Millitokens String>
58
- [request]: <Bolt 11 Invoice String>
59
- secret: <Secret Preimage Hex String>
60
- tokens: <Tokens Number>
61
- }]
62
- }
63
- */
64
- module.exports = (args, cbk) => {
65
- return new Promise((resolve, reject) => {
66
- return asyncAuto({
67
- // Check arguments
68
- validate: cbk => {
69
- if (!args.lnd) {
70
- return cbk([400, 'ExpectedAuthenticatedLndToGetAllInvoices']);
71
- }
72
-
73
- return cbk();
74
- },
75
-
76
- // Get all the invoices
77
- getInvoices: ['validate', ({}, cbk) => {
78
- const confAfter = args.confirmed_after;
79
- const createdAfter = args.created_after;
80
- const invoices = [];
81
- let token;
82
-
83
- return asyncUntil(
84
- cbk => cbk(null, token === false),
85
- cbk => {
86
- return getInvoices({
87
- token,
88
- limit: !token ? defaultInvoicesLimit : undefined,
89
- lnd: args.lnd,
90
- },
91
- (err, res) => {
92
- if (!!err) {
93
- return cbk(err);
94
- }
95
-
96
- token = res.next || false;
97
-
98
- res.invoices
99
- .filter(n => !confAfter || n.confirmed_at >= confAfter)
100
- .filter(n => !createdAfter || n.created_at >= createdAfter)
101
- .forEach(n => invoices.push(n));
102
-
103
- const createdAt = res.invoices.map(n => n.created_at);
104
-
105
- // Stop paging when created after is set
106
- if (!!createdAfter && createdAt.find(n => n < createdAfter)) {
107
- token = false;
108
- }
109
-
110
- return cbk();
111
- });
112
- },
113
- err => {
114
- if (!!err) {
115
- return cbk(err);
116
- }
117
-
118
- return cbk(null, {invoices});
119
- }
120
- );
121
- }],
122
- },
123
- returnResult({reject, resolve, of: 'getInvoices'}, cbk));
124
- });
125
- };